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,1743 @@
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 uuid
16
+ from datetime import datetime, timedelta
17
+ from typing import TYPE_CHECKING, Any, Optional, Union
18
+
19
+ from sqlalchemy import BigInteger, Boolean, DateTime, Enum, Float, Integer, SmallInteger, String, Text, UniqueConstraint, event
20
+ from sqlalchemy.engine import Engine
21
+ from sqlalchemy.ext.compiler import compiles
22
+ from sqlalchemy.ext.declarative import declared_attr
23
+ from sqlalchemy.orm import Mapped, mapped_column, object_mapper, relationship
24
+ from sqlalchemy.schema import CheckConstraint, ForeignKeyConstraint, Index, PrimaryKeyConstraint, Table
25
+ from sqlalchemy.sql import Delete
26
+ from sqlalchemy.types import LargeBinary
27
+
28
+ # schema must be imported as a module to avoid circular imports with policy packages,
29
+ # and it must be renamed to avoid conflicts with the policy package schema modules
30
+ from rucio.common import schema as common_schema
31
+ from rucio.common import utils
32
+ from rucio.common.types import InternalAccount, InternalScope # noqa: TCH001 (types are needed by SQLAlchemy)
33
+ from rucio.db.sqla.constants import (
34
+ AccountStatus,
35
+ AccountType,
36
+ BadFilesStatus,
37
+ BadPFNStatus,
38
+ DIDAvailability,
39
+ DIDReEvaluation,
40
+ DIDType,
41
+ IdentityType,
42
+ KeyType,
43
+ LifetimeExceptionsState,
44
+ LockState,
45
+ ReplicaState,
46
+ RequestState,
47
+ RequestType,
48
+ RSEType,
49
+ RuleGrouping,
50
+ RuleNotification,
51
+ RuleState,
52
+ ScopeStatus,
53
+ SubscriptionState,
54
+ TransferLimitDirection,
55
+ )
56
+ from rucio.db.sqla.session import BASE
57
+ from rucio.db.sqla.types import GUID, JSON, BooleanString, InternalAccountString, InternalScopeString
58
+
59
+ if TYPE_CHECKING:
60
+ from sqlalchemy.engine.base import Connection
61
+ from sqlalchemy.orm import Session
62
+ from sqlalchemy.sql import Insert, Update
63
+
64
+
65
+ # SQLAlchemy defines the corresponding code behind TYPE_CHECKING
66
+ # https://github.com/sqlalchemy/sqlalchemy/blob/d9acd6223299c118464d30abfa483e26a536239d/lib/sqlalchemy/orm/base.py#L814
67
+ # And pylint/astroid don't have an option to evaluate this code
68
+ # https://github.com/pylint-dev/astroid/issues/1332
69
+ # So we get this error all over the place: `E1136: Value 'Mapped' is unsubscriptable (unsubscriptable-object)`
70
+ #
71
+ # pylint: disable=E1136
72
+
73
+
74
+ @compiles(Boolean, "oracle")
75
+ def compile_binary_oracle(type_, compiler, **kw) -> str:
76
+ return "NUMBER(1)"
77
+
78
+
79
+ @event.listens_for(Table, "before_create")
80
+ def _mysql_rename_type(target: Table, connection: "Connection", **kw) -> None:
81
+ if connection.dialect.name == 'mysql' and target.name == 'quarantined_replicas':
82
+ target.columns.path.type = String(255)
83
+
84
+
85
+ @event.listens_for(Table, "before_create")
86
+ def _psql_rename_type(target: Table, connection: "Connection", **kw) -> None:
87
+ if connection.dialect.name == 'postgresql' and target.name == 'account_map':
88
+ target.columns.identity_type.type.name = 'IDENTITIES_TYPE_CHK'
89
+
90
+
91
+ @event.listens_for(Table, "before_create")
92
+ def _oracle_json_constraint(target: Table, connection: "Connection", **kw) -> None:
93
+ if connection.dialect.name == 'oracle':
94
+ try:
95
+ oracle_version = int(connection.connection.version.split('.')[0])
96
+ except Exception:
97
+ return
98
+ if oracle_version >= 12:
99
+ if target.name == 'did_meta':
100
+ target.append_constraint(CheckConstraint('META IS JSON', 'ORACLE_META_JSON_CHK'))
101
+ if target.name == 'deleted_did_meta':
102
+ target.append_constraint(CheckConstraint('META IS JSON', 'ORACLE_DELETE_META_JSON_CHK'))
103
+ if target.name == 'virtual_placements':
104
+ target.append_constraint(CheckConstraint('PLACEMENTS IS JSON', 'ORACLE_PLACEMENTS_JSON_CHK'))
105
+
106
+
107
+ @event.listens_for(Engine, "before_execute", retval=True)
108
+ def _add_hint(
109
+ conn: "Connection",
110
+ element: Union[Delete, "Insert", "Update"],
111
+ multiparams,
112
+ params,
113
+ execution_options
114
+ ) -> tuple[Union[Delete, "Insert", "Update"], list, dict]:
115
+ if conn.dialect.name == 'oracle' and isinstance(element, Delete) and element.table.name == 'locks':
116
+ element = element.prefix_with("/*+ INDEX(LOCKS LOCKS_PK) */")
117
+ if conn.dialect.name == 'oracle' and isinstance(element, Delete) and element.table.name == 'replicas':
118
+ element = element.prefix_with("/*+ INDEX(REPLICAS REPLICAS_PK) */")
119
+ if conn.dialect.name == 'oracle' and isinstance(element, Delete) and element.table.name == 'dids':
120
+ element = element.prefix_with("/*+ INDEX(DIDS DIDS_PK) */")
121
+ if conn.dialect.name == 'oracle' and isinstance(element, Delete) and element.table.name == 'updated_dids':
122
+ element = element.prefix_with("/*+ INDEX(updated_dids UPDATED_DIDS_SCOPERULENAME_IDX) */")
123
+ if conn.dialect.name == 'oracle' and isinstance(element, Delete) and element.table.name == 'tokens':
124
+ element = element.prefix_with("/*+ INDEX(TOKENS_ACCOUNT_EXPIRED_AT_IDX) */")
125
+ return element, multiparams, params
126
+
127
+
128
+ @event.listens_for(PrimaryKeyConstraint, "after_parent_attach")
129
+ def _pk_constraint_name(const: PrimaryKeyConstraint, table: Table) -> None:
130
+ if table.name.upper() == 'QUARANTINED_REPLICAS_HISTORY':
131
+ const.name = "QRD_REPLICAS_HISTORY_PK"
132
+ else:
133
+ const.name = "%s_PK" % (table.name.upper(),)
134
+
135
+
136
+ @event.listens_for(ForeignKeyConstraint, "after_parent_attach")
137
+ def _fk_constraint_name(const: ForeignKeyConstraint, table: Table) -> None:
138
+ if const.name:
139
+ return
140
+ fk = const.elements[0]
141
+ reftable, refcol = fk.target_fullname.split(".")
142
+ const.name = "fk_%s_%s_%s" % (table.name,
143
+ fk.parent.name,
144
+ reftable)
145
+
146
+
147
+ @event.listens_for(UniqueConstraint, "after_parent_attach")
148
+ def _unique_constraint_name(const: UniqueConstraint, table: Table) -> None:
149
+ if const.name:
150
+ return
151
+ const.name = "uq_%s_%s" % (table.name, list(const.columns)[0].name)
152
+
153
+
154
+ @event.listens_for(CheckConstraint, "after_parent_attach")
155
+ def _ck_constraint_name(const: CheckConstraint, table: Table) -> None:
156
+
157
+ if const.name is None:
158
+ if 'DELETED' in str(const.sqltext).upper():
159
+ if len(table.name) > 20:
160
+ const.name = "%s_DEL_CHK" % (table.name.upper())
161
+ else:
162
+ const.name = "%s_DELETED_CHK" % (table.name.upper())
163
+ elif const.name == 'SUBSCRIPTIONS_RETROACTIVE_CHK' and table.name.upper() == 'SUBSCRIPTIONS_HISTORY':
164
+ const.name = "SUBS_HISTORY_RETROACTIVE_CHK"
165
+ elif const.name == 'SUBSCRIPTIONS_STATE_CHK' and table.name.upper() == 'SUBSCRIPTIONS_HISTORY':
166
+ const.name = "SUBS_HISTORY_STATE_CHK"
167
+ elif const.name == 'QUARANTINED_REPLICAS_CREATED_NN' and table.name.upper() == 'QUARANTINED_REPLICAS':
168
+ const.name = "QURD_REPLICAS_CREATED_NN"
169
+ elif const.name == 'QUARANTINED_REPLICAS_UPDATED_NN' and table.name.upper() == 'QUARANTINED_REPLICAS':
170
+ const.name = "QURD_REPLICAS_UPDATED_NN"
171
+ elif const.name == 'QUARANTINED_REPLICAS_HISTORY_CREATED_NN' and table.name.upper() == 'QUARANTINED_REPLICAS_HISTORY':
172
+ const.name = "QURD_REPLICAS_HIST_CREATED_NN"
173
+ elif const.name == 'QUARANTINED_REPLICAS_HISTORY_UPDATED_NN' and table.name.upper() == 'QUARANTINED_REPLICAS_HISTORY':
174
+ const.name = "QURD_REPLICAS_HIST_UPDATED_NN"
175
+ elif const.name == 'ARCHIVE_CONTENTS_HISTORY_CREATED_NN' and table.name.upper() == 'ARCHIVE_CONTENTS_HISTORY':
176
+ const.name = "ARCH_CNTS_HIST_CREATED_NN"
177
+ elif const.name == 'ARCHIVE_CONTENTS_HISTORY_UPDATED_NN' and table.name.upper() == 'ARCHIVE_CONTENTS_HISTORY':
178
+ const.name = "ARCH_CNTS_HIST_UPDATED_NN"
179
+ elif const.name == 'ACCOUNT_USAGE_HISTORY_CREATED_NN' and table.name.upper() == 'ACCOUNT_USAGE_HISTORY':
180
+ const.name = "ACCOUNT_USAGE_HIST_CREATED_NN"
181
+ elif const.name == 'ACCOUNT_USAGE_HISTORY_UPDATED_NN' and table.name.upper() == 'ACCOUNT_USAGE_HISTORY':
182
+ const.name = "ACCOUNT_USAGE_HIST_UPDATED_NN"
183
+ elif const.name == 'SUBSCRIPTIONS_HISTORY_CREATED_NN' and table.name.upper() == 'SUBSCRIPTIONS_HISTORY':
184
+ const.name = "SUBSCRIPTIONS_HIST_CREATED_NN"
185
+ elif const.name == 'SUBSCRIPTIONS_HISTORY_UPDATED_NN' and table.name.upper() == 'SUBSCRIPTIONS_HISTORY':
186
+ const.name = "SUBSCRIPTIONS_HIST_UPDATED_NN"
187
+
188
+ if const.name is None:
189
+ const.name = table.name.upper() + '_' + str(uuid.uuid4())[:6] + '_CHK'
190
+
191
+ if const.name == 'REQUESTS_TYPE_CHK' and table.name.upper() == 'REQUESTS_HISTORY':
192
+ const.name = "REQUESTS_HISTORY_TYPE_CHK"
193
+ elif const.name == 'REQUESTS_DIDTYPE_CHK' and table.name.upper() == 'REQUESTS_HISTORY':
194
+ const.name = "REQUESTS_HISTORY_DIDTYPE_CHK"
195
+ elif const.name == 'REQUESTS_DIDTYPE_CHK' and table.name.upper() == 'REQUESTS_HISTORY':
196
+ const.name = "REQUESTS_HISTORY_DIDTYPE_CHK"
197
+ elif const.name == 'REQUESTS_STATE_CHK' and table.name.upper() == 'REQUESTS_HISTORY':
198
+ const.name = "REQUESTS_HISTORY_STATE_CHK"
199
+
200
+
201
+ class ModelBase:
202
+ """Base class for Rucio Models"""
203
+ __table_initialized__ = False
204
+
205
+ @declared_attr
206
+ def __table_args__(cls): # pylint: disable=no-self-argument
207
+ # exception for CERN Oracle identifier length limitations
208
+ # pylint: disable=maybe-no-member
209
+ if cls.__tablename__.upper() == 'UPDATED_ACCOUNT_COUNTERS':
210
+ return cls._table_args + (CheckConstraint('CREATED_AT IS NOT NULL', 'UPDATED_ACCNT_CNTRS_CREATED_NN'),
211
+ CheckConstraint('UPDATED_AT IS NOT NULL', 'UPDATED_ACCNT_CNTRS_UPDATED_NN'),
212
+ {'mysql_engine': 'InnoDB'})
213
+ # pylint: disable=maybe-no-member
214
+ elif cls.__tablename__.upper() == 'UPDATED_RSE_COUNTERS':
215
+ return cls._table_args + (CheckConstraint('CREATED_AT IS NOT NULL', 'UPDATED_RSE_CNTRS_CREATED_NN'),
216
+ CheckConstraint('UPDATED_AT IS NOT NULL', 'UPDATED_RSE_CNTRS_UPDATED_NN'),
217
+ {'mysql_engine': 'InnoDB'})
218
+ # pylint: disable=maybe-no-member
219
+ elif cls.__tablename__.upper() == 'DIDS_FOLLOWED_EVENTS':
220
+ return cls._table_args + (CheckConstraint('CREATED_AT IS NOT NULL', 'DIDS_FOLLOWED_EVENTS_CRE_NN'),
221
+ CheckConstraint('UPDATED_AT IS NOT NULL', 'DIDS_FOLLOWED_EVENTS_UPD_NN'),
222
+ {'mysql_engine': 'InnoDB'})
223
+
224
+ # otherwise, proceed normally
225
+ # pylint: disable=maybe-no-member
226
+ return cls._table_args + (CheckConstraint('CREATED_AT IS NOT NULL', name=cls.__tablename__.upper() + '_CREATED_NN'),
227
+ CheckConstraint('UPDATED_AT IS NOT NULL', name=cls.__tablename__.upper() + '_UPDATED_NN'),
228
+ {'mysql_engine': 'InnoDB'})
229
+
230
+ @declared_attr
231
+ def created_at(cls): # pylint: disable=no-self-argument
232
+ return mapped_column("created_at", DateTime, default=datetime.utcnow)
233
+
234
+ @declared_attr
235
+ def updated_at(cls): # pylint: disable=no-self-argument
236
+ return mapped_column("updated_at", DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
237
+
238
+ def save(self, flush: bool = True, session: Optional["Session"] = None) -> None:
239
+ """Save this object"""
240
+ # Sessions created with autoflush: bool = True be default since sqlAlchemy 1.4.
241
+ # So explicitly calling session.flush is not necessary.
242
+ # However, when autogenerated primary keys involved, calling
243
+ # session.flush to get the id from DB.
244
+ session.add(self)
245
+ if flush:
246
+ session.flush()
247
+
248
+ def delete(self, flush: bool = True, session: Optional["Session"] = None) -> None:
249
+ """Delete this object"""
250
+ session.delete(self)
251
+ if flush:
252
+ session.flush()
253
+
254
+ def update(self, values: dict[str, Any], flush: bool = True, session: Optional["Session"] = None) -> None:
255
+ """dict.update() behaviour."""
256
+ for k, v in values.items():
257
+ self[k] = v
258
+ if session and flush:
259
+ session.flush()
260
+
261
+ def __setitem__(self, key, value):
262
+ setattr(self, key, value)
263
+
264
+ def __getitem__(self, key):
265
+ return getattr(self, key)
266
+
267
+ def __iter__(self):
268
+ self._i = iter(object_mapper(self).columns)
269
+ return self
270
+
271
+ def __next__(self):
272
+ n = next(self._i).name
273
+ return n, getattr(self, n)
274
+
275
+ def keys(self):
276
+ return list(self.__dict__.keys())
277
+
278
+ def values(self):
279
+ return list(self.__dict__.values())
280
+
281
+ def items(self):
282
+ return list(self.__dict__.items())
283
+
284
+ def to_dict(self):
285
+ dictionary = self.__dict__.copy()
286
+ dictionary.pop('_sa_instance_state')
287
+ return dictionary
288
+
289
+ next = __next__
290
+
291
+
292
+ class SoftModelBase(ModelBase):
293
+ """Base class for Rucio Models with soft-deletion support"""
294
+ __table_initialized__ = False
295
+
296
+ @declared_attr
297
+ def __table_args__(cls): # pylint: disable=no-self-argument
298
+ # pylint: disable=maybe-no-member
299
+ return cls._table_args + (CheckConstraint('CREATED_AT IS NOT NULL', name=cls.__tablename__.upper() + '_CREATED_NN'),
300
+ CheckConstraint('UPDATED_AT IS NOT NULL', name=cls.__tablename__.upper() + '_UPDATED_NN'),
301
+ CheckConstraint('DELETED IS NOT NULL', name=cls.__tablename__.upper() + '_DELETED_NN'),
302
+ {'mysql_engine': 'InnoDB'})
303
+
304
+ @declared_attr
305
+ def deleted(cls): # pylint: disable=no-self-argument
306
+ return mapped_column("deleted", Boolean, default=False)
307
+
308
+ @declared_attr
309
+ def deleted_at(cls): # pylint: disable=no-self-argument
310
+ return mapped_column("deleted_at", DateTime)
311
+
312
+ def delete(self, flush: bool = True, session: Optional["Session"] = None) -> None:
313
+ """Delete this object"""
314
+ self.deleted = True
315
+ self.deleted_at = datetime.utcnow()
316
+ self.save(session=session)
317
+
318
+
319
+ class Account(BASE, ModelBase):
320
+ """Represents an account"""
321
+ __tablename__ = 'accounts'
322
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
323
+ account_type: Mapped[AccountType] = mapped_column(Enum(AccountType, name='ACCOUNTS_TYPE_CHK',
324
+ create_constraint=True,
325
+ values_callable=lambda obj: [e.value for e in obj]))
326
+ status: Mapped[AccountStatus] = mapped_column(Enum(AccountStatus, name='ACCOUNTS_STATUS_CHK',
327
+ create_constraint=True,
328
+ values_callable=lambda obj: [e.value for e in obj]),
329
+ default=AccountStatus.ACTIVE, )
330
+ email: Mapped[Optional[str]] = mapped_column(String(255))
331
+ suspended_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
332
+ deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
333
+ _table_args = (PrimaryKeyConstraint('account', name='ACCOUNTS_PK'),
334
+ CheckConstraint('ACCOUNT_TYPE IS NOT NULL', name='ACCOUNTS_TYPE_NN'),
335
+ CheckConstraint('STATUS IS NOT NULL', name='ACCOUNTS_STATUS_NN'))
336
+
337
+
338
+ class AccountAttrAssociation(BASE, ModelBase):
339
+ """Represents an account"""
340
+ __tablename__ = 'account_attr_map'
341
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
342
+ key: Mapped[str] = mapped_column(String(255))
343
+ value: Mapped[Optional[Union[bool, str]]] = mapped_column(BooleanString(255))
344
+ _table_args = (PrimaryKeyConstraint('account', 'key', name='ACCOUNT_ATTR_MAP_PK'),
345
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='ACCOUNT_ATTR_MAP_ACCOUNT_FK'),
346
+ Index('ACCOUNT_ATTR_MAP_KEY_VALUE_IDX', 'key', 'value'))
347
+
348
+
349
+ class Identity(BASE, SoftModelBase):
350
+ """Represents an identity"""
351
+ __tablename__ = 'identities'
352
+ identity: Mapped[str] = mapped_column(String(2048))
353
+ identity_type: Mapped[IdentityType] = mapped_column(Enum(IdentityType, name='IDENTITIES_TYPE_CHK',
354
+ create_constraint=True,
355
+ values_callable=lambda obj: [e.value for e in obj]))
356
+ username: Mapped[Optional[str]] = mapped_column(String(255))
357
+ password: Mapped[Optional[str]] = mapped_column(String(255))
358
+ salt = mapped_column(LargeBinary(255))
359
+ email: Mapped[str] = mapped_column(String(255))
360
+ _table_args = (PrimaryKeyConstraint('identity', 'identity_type', name='IDENTITIES_PK'),
361
+ CheckConstraint('IDENTITY_TYPE IS NOT NULL', name='IDENTITIES_TYPE_NN'),
362
+ CheckConstraint('EMAIL IS NOT NULL', name='IDENTITIES_EMAIL_NN'))
363
+
364
+
365
+ class IdentityAccountAssociation(BASE, ModelBase):
366
+ """Represents a map account-identity"""
367
+ __tablename__ = 'account_map'
368
+ identity: Mapped[str] = mapped_column(String(2048))
369
+ identity_type: Mapped[IdentityType] = mapped_column(Enum(IdentityType, name='ACCOUNT_MAP_ID_TYPE_CHK',
370
+ create_constraint=True,
371
+ values_callable=lambda obj: [e.value for e in obj]))
372
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
373
+ is_default: Mapped[bool] = mapped_column(Boolean(name='ACCOUNT_MAP_DEFAULT_CHK', create_constraint=True),
374
+ default=False)
375
+ _table_args = (PrimaryKeyConstraint('identity', 'identity_type', 'account', name='ACCOUNT_MAP_PK'),
376
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='ACCOUNT_MAP_ACCOUNT_FK'),
377
+ ForeignKeyConstraint(['identity', 'identity_type'], ['identities.identity', 'identities.identity_type'], name='ACCOUNT_MAP_ID_TYPE_FK'),
378
+ CheckConstraint('is_default IS NOT NULL', name='ACCOUNT_MAP_IS_DEFAULT_NN'),
379
+ CheckConstraint('IDENTITY_TYPE IS NOT NULL', name='ACCOUNT_MAP_ID_TYPE_NN'))
380
+
381
+
382
+ class Scope(BASE, ModelBase):
383
+ """Represents a scope"""
384
+ __tablename__ = 'scopes'
385
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
386
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
387
+ is_default: Mapped[bool] = mapped_column(Boolean(name='SCOPES_DEFAULT_CHK', create_constraint=True),
388
+ default=False)
389
+ status: Mapped[ScopeStatus] = mapped_column(Enum(ScopeStatus, name='SCOPE_STATUS_CHK',
390
+ create_constraint=True,
391
+ values_callable=lambda obj: [e.value for e in obj]),
392
+ default=ScopeStatus.OPEN)
393
+ closed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
394
+ deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
395
+ _table_args = (PrimaryKeyConstraint('scope', name='SCOPES_SCOPE_PK'),
396
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='SCOPES_ACCOUNT_FK'),
397
+ CheckConstraint('is_default IS NOT NULL', name='SCOPES_IS_DEFAULT_NN'),
398
+ CheckConstraint('STATUS IS NOT NULL', name='SCOPES_STATUS_NN'),
399
+ CheckConstraint('ACCOUNT IS NOT NULL', name='SCOPES_ACCOUNT_NN'))
400
+
401
+
402
+ class DataIdentifier(BASE, ModelBase):
403
+ """Represents a dataset"""
404
+ __tablename__ = 'dids'
405
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
406
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
407
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
408
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='DIDS_TYPE_CHK',
409
+ create_constraint=True,
410
+ values_callable=lambda obj: [e.value for e in obj]))
411
+ is_open: Mapped[Optional[bool]] = mapped_column(Boolean(name='DIDS_IS_OPEN_CHK', create_constraint=True))
412
+ monotonic: Mapped[bool] = mapped_column(Boolean(name='DIDS_MONOTONIC_CHK', create_constraint=True),
413
+ server_default='0')
414
+ hidden: Mapped[bool] = mapped_column(Boolean(name='DIDS_HIDDEN_CHK', create_constraint=True),
415
+ server_default='0')
416
+ obsolete: Mapped[bool] = mapped_column(Boolean(name='DIDS_OBSOLETE_CHK', create_constraint=True),
417
+ server_default='0')
418
+ complete: Mapped[Optional[bool]] = mapped_column(Boolean(name='DIDS_COMPLETE_CHK', create_constraint=True),
419
+ server_default=None)
420
+ is_new: Mapped[Optional[bool]] = mapped_column(Boolean(name='DIDS_IS_NEW_CHK', create_constraint=True),
421
+ server_default='1')
422
+ availability: Mapped[DIDAvailability] = mapped_column(Enum(DIDAvailability, name='DIDS_AVAILABILITY_CHK',
423
+ create_constraint=True,
424
+ values_callable=lambda obj: [e.value for e in obj]),
425
+ default=DIDAvailability.AVAILABLE)
426
+ suppressed: Mapped[bool] = mapped_column(Boolean(name='FILES_SUPP_CHK', create_constraint=True),
427
+ server_default='0')
428
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
429
+ length: Mapped[Optional[int]] = mapped_column(BigInteger)
430
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
431
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
432
+ expired_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
433
+ purge_replicas: Mapped[bool] = mapped_column(Boolean(name='DIDS_PURGE_RPLCS_CHK', create_constraint=True),
434
+ server_default='1')
435
+ deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
436
+ # hardcoded meta-data to populate the db
437
+ events: Mapped[Optional[int]] = mapped_column(BigInteger)
438
+ guid: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
439
+ project: Mapped[Optional[str]] = mapped_column(String(50))
440
+ datatype: Mapped[Optional[str]] = mapped_column(String(50))
441
+ run_number: Mapped[Optional[int]] = mapped_column(Integer)
442
+ stream_name: Mapped[Optional[str]] = mapped_column(String(70))
443
+ prod_step: Mapped[Optional[str]] = mapped_column(String(50))
444
+ version: Mapped[Optional[str]] = mapped_column(String(50))
445
+ campaign: Mapped[Optional[str]] = mapped_column(String(50))
446
+ task_id: Mapped[Optional[int]] = mapped_column(Integer())
447
+ panda_id: Mapped[Optional[int]] = mapped_column(Integer())
448
+ lumiblocknr: Mapped[Optional[int]] = mapped_column(Integer())
449
+ provenance: Mapped[Optional[str]] = mapped_column(String(2))
450
+ phys_group: Mapped[Optional[str]] = mapped_column(String(25))
451
+ transient: Mapped[bool] = mapped_column(Boolean(name='DID_TRANSIENT_CHK', create_constraint=True),
452
+ server_default='0')
453
+ accessed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
454
+ closed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
455
+ eol_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
456
+ is_archive: Mapped[Optional[bool]] = mapped_column(Boolean(name='DIDS_ARCHIVE_CHK', create_constraint=True))
457
+ constituent: Mapped[Optional[bool]] = mapped_column(Boolean(name='DIDS_CONSTITUENT_CHK', create_constraint=True))
458
+ access_cnt: Mapped[Optional[int]] = mapped_column(Integer())
459
+ _table_args = (PrimaryKeyConstraint('scope', 'name', name='DIDS_PK'),
460
+ ForeignKeyConstraint(['account'], ['accounts.account'], ondelete='CASCADE', name='DIDS_ACCOUNT_FK'),
461
+ ForeignKeyConstraint(['scope'], ['scopes.scope'], name='DIDS_SCOPE_FK'),
462
+ CheckConstraint('MONOTONIC IS NOT NULL', name='DIDS_MONOTONIC_NN'),
463
+ CheckConstraint('OBSOLETE IS NOT NULL', name='DIDS_OBSOLETE_NN'),
464
+ CheckConstraint('SUPPRESSED IS NOT NULL', name='DIDS_SUPP_NN'),
465
+ CheckConstraint('ACCOUNT IS NOT NULL', name='DIDS_ACCOUNT_NN'),
466
+ CheckConstraint('PURGE_REPLICAS IS NOT NULL', name='DIDS_PURGE_REPLICAS_NN'),
467
+ Index('DIDS_IS_NEW_IDX', 'is_new'),
468
+ Index('DIDS_EXPIRED_AT_IDX', 'expired_at'))
469
+
470
+
471
+ class VirtualPlacements(BASE, ModelBase):
472
+ """Represents virtual placements"""
473
+ __tablename__ = 'virtual_placements'
474
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
475
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
476
+ placements = mapped_column(JSON())
477
+ _table_args = (PrimaryKeyConstraint('scope', 'name', name='VP_PK'),
478
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'], name='VP_FK')
479
+ )
480
+
481
+
482
+ class DidMeta(BASE, ModelBase):
483
+ __tablename__ = 'did_meta'
484
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
485
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
486
+ meta: Mapped[Optional[Union[str, dict[str, Any]]]] = mapped_column(JSON())
487
+ did_type: Mapped[Optional[DIDType]] = mapped_column(Enum(DIDType, name='DID_META_DID_TYPE_CHK',
488
+ create_constraint=True,
489
+ values_callable=lambda obj: [e.value for e in obj]))
490
+ _table_args = (PrimaryKeyConstraint('scope', 'name', name='DID_META_PK'),
491
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'], name='DID_META_FK'),
492
+ Index('DID_META_DID_TYPE_IDX', 'did_type'))
493
+
494
+
495
+ class DeletedDidMeta(BASE, ModelBase):
496
+ __tablename__ = 'deleted_did_meta'
497
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
498
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
499
+ did_type: Mapped[Optional[DIDType]] = mapped_column(Enum(DIDType, name='DEL_DID_META_DID_TYPE_CHK',
500
+ create_constraint=True,
501
+ values_callable=lambda obj: [e.value for e in obj]))
502
+ meta: Mapped[Optional[Union[str, dict[str, Any]]]] = mapped_column(JSON())
503
+ deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
504
+ _table_args = (PrimaryKeyConstraint('scope', 'name', name='DEL_DID_META_PK'),
505
+ Index('DEL_DID_META_DID_TYPE_IDX', 'did_type'))
506
+
507
+
508
+ class DeletedDataIdentifier(BASE, ModelBase):
509
+ """Represents a dataset"""
510
+ __tablename__ = 'deleted_dids'
511
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
512
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
513
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
514
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='DEL_DIDS_TYPE_CHK',
515
+ create_constraint=True,
516
+ values_callable=lambda obj: [e.value for e in obj]))
517
+ is_open: Mapped[Optional[bool]] = mapped_column(Boolean(name='DEL_DIDS_IS_OPEN_CHK', create_constraint=True))
518
+ monotonic: Mapped[bool] = mapped_column(Boolean(name='DEL_DIDS_MONO_CHK', create_constraint=True),
519
+ server_default='0')
520
+ hidden: Mapped[bool] = mapped_column(Boolean(name='DEL_DIDS_HIDDEN_CHK', create_constraint=True),
521
+ server_default='0')
522
+ obsolete: Mapped[bool] = mapped_column(Boolean(name='DEL_DIDS_OBSOLETE_CHK', create_constraint=True),
523
+ server_default='0')
524
+ complete: Mapped[Optional[bool]] = mapped_column(Boolean(name='DEL_DIDS_COMPLETE_CHK', create_constraint=True))
525
+ is_new: Mapped[Optional[bool]] = mapped_column(Boolean(name='DEL_DIDS_IS_NEW_CHK', create_constraint=True),
526
+ server_default='1')
527
+ availability: Mapped[DIDAvailability] = mapped_column(Enum(DIDAvailability, name='DEL_DIDS_AVAIL_CHK',
528
+ create_constraint=True,
529
+ values_callable=lambda obj: [e.value for e in obj]),
530
+ default=DIDAvailability.AVAILABLE)
531
+ suppressed: Mapped[bool] = mapped_column(Boolean(name='DEL_FILES_SUPP_CHK', create_constraint=True),
532
+ server_default='0')
533
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
534
+ length: Mapped[Optional[int]] = mapped_column(BigInteger)
535
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
536
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
537
+ expired_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
538
+ deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
539
+ events: Mapped[Optional[int]] = mapped_column(BigInteger)
540
+ guid: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
541
+ project: Mapped[Optional[str]] = mapped_column(String(50))
542
+ datatype: Mapped[Optional[str]] = mapped_column(String(50))
543
+ run_number: Mapped[Optional[int]] = mapped_column(Integer)
544
+ stream_name: Mapped[Optional[str]] = mapped_column(String(70))
545
+ prod_step: Mapped[Optional[str]] = mapped_column(String(50))
546
+ version: Mapped[Optional[str]] = mapped_column(String(50))
547
+ campaign: Mapped[Optional[str]] = mapped_column(String(50))
548
+ task_id: Mapped[Optional[int]] = mapped_column(Integer())
549
+ panda_id: Mapped[Optional[int]] = mapped_column(Integer())
550
+ lumiblocknr: Mapped[Optional[int]] = mapped_column(Integer())
551
+ provenance: Mapped[Optional[str]] = mapped_column(String(2))
552
+ phys_group: Mapped[Optional[str]] = mapped_column(String(25))
553
+ transient: Mapped[bool] = mapped_column(Boolean(name='DEL_DID_TRANSIENT_CHK', create_constraint=True),
554
+ server_default='0')
555
+ purge_replicas: Mapped[Optional[bool]] = mapped_column(Boolean(name='DELETED_DIDS_PURGE_RPLCS_CHK', create_constraint=True))
556
+ accessed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
557
+ closed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
558
+ eol_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
559
+ is_archive: Mapped[Optional[bool]] = mapped_column(Boolean(name='DEL_DIDS_ARCH_CHK', create_constraint=True))
560
+ constituent: Mapped[Optional[bool]] = mapped_column(Boolean(name='DEL_DIDS_CONST_CHK', create_constraint=True))
561
+ access_cnt: Mapped[Optional[int]] = mapped_column(Integer())
562
+ _table_args = (PrimaryKeyConstraint('scope', 'name', name='DELETED_DIDS_PK'), )
563
+
564
+
565
+ class UpdatedDID(BASE, ModelBase):
566
+ """Represents the recently updated dids"""
567
+ __tablename__ = 'updated_dids'
568
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
569
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
570
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
571
+ rule_evaluation_action: Mapped[DIDReEvaluation] = mapped_column(Enum(DIDReEvaluation, name='UPDATED_DIDS_RULE_EVAL_ACT_CHK',
572
+ create_constraint=True,
573
+ values_callable=lambda obj: [e.value for e in obj]))
574
+ _table_args = (PrimaryKeyConstraint('id', name='UPDATED_DIDS_PK'),
575
+ CheckConstraint('SCOPE IS NOT NULL', name='UPDATED_DIDS_SCOPE_NN'),
576
+ CheckConstraint('NAME IS NOT NULL', name='UPDATED_DIDS_NAME_NN'),
577
+ Index('UPDATED_DIDS_SCOPERULENAME_IDX', 'scope', 'rule_evaluation_action', 'name'))
578
+
579
+
580
+ class BadReplica(BASE, ModelBase):
581
+ """Represents the suspicious or bad replicas"""
582
+ __tablename__ = 'bad_replicas'
583
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
584
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
585
+ rse_id: Mapped[str] = mapped_column(GUID())
586
+ reason: Mapped[Optional[str]] = mapped_column(String(255))
587
+ state: Mapped[BadFilesStatus] = mapped_column(Enum(BadFilesStatus, name='BAD_REPLICAS_STATE_CHK',
588
+ create_constraint=True,
589
+ values_callable=lambda obj: [e.value for e in obj]),
590
+ default=BadFilesStatus.SUSPICIOUS)
591
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
592
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
593
+ expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
594
+ _table_args = (PrimaryKeyConstraint('scope', 'name', 'rse_id', 'state', 'created_at', name='BAD_REPLICAS_STATE_PK'),
595
+ CheckConstraint('SCOPE IS NOT NULL', name='BAD_REPLICAS_SCOPE_NN'),
596
+ CheckConstraint('NAME IS NOT NULL', name='BAD_REPLICAS_NAME_NN'),
597
+ CheckConstraint('RSE_ID IS NOT NULL', name='BAD_REPLICAS_RSE_ID_NN'),
598
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='BAD_REPLICAS_ACCOUNT_FK'),
599
+ Index('BAD_REPLICAS_STATE_IDX', 'rse_id', 'state'),
600
+ Index('BAD_REPLICAS_EXPIRES_AT_IDX', 'expires_at'),
601
+ Index('BAD_REPLICAS_ACCOUNT_IDX', 'account'))
602
+
603
+
604
+ class BadPFN(BASE, ModelBase):
605
+ """Represents bad, suspicious or temporary unavailable PFNs which have to be processed and added to BadReplica Table"""
606
+ __tablename__ = 'bad_pfns'
607
+ path: Mapped[str] = mapped_column(String(2048)) # PREFIX + PFN
608
+ state: Mapped[BadPFNStatus] = mapped_column(Enum(BadPFNStatus, name='BAD_PFNS_STATE_CHK',
609
+ create_constraint=True,
610
+ values_callable=lambda obj: [e.value for e in obj]),
611
+ default=BadPFNStatus.SUSPICIOUS)
612
+ reason: Mapped[Optional[str]] = mapped_column(String(255))
613
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
614
+ expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
615
+ _table_args = (PrimaryKeyConstraint('path', 'state', name='BAD_PFNS_PK'),
616
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='BAD_PFNS_ACCOUNT_FK'))
617
+
618
+
619
+ class QuarantinedReplica(BASE, ModelBase):
620
+ """Represents the quarantined replicas"""
621
+ __tablename__ = 'quarantined_replicas'
622
+ rse_id: Mapped[str] = mapped_column(GUID())
623
+ path: Mapped[str] = mapped_column(String(1024))
624
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
625
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
626
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
627
+ scope: Mapped[Optional[InternalScope]] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
628
+ name: Mapped[Optional[str]] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
629
+ _table_args = (PrimaryKeyConstraint('rse_id', 'path', name='QURD_REPLICAS_STATE_PK'),
630
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='QURD_REPLICAS_RSE_ID_FK'),
631
+ Index('QUARANTINED_REPLICAS_PATH_IDX', 'path', 'rse_id', unique=True))
632
+
633
+
634
+ class QuarantinedReplicaHistory(BASE, ModelBase):
635
+ """Represents the quarantined replicas history"""
636
+ __tablename__ = 'quarantined_replicas_history'
637
+ rse_id: Mapped[str] = mapped_column(GUID())
638
+ path: Mapped[str] = mapped_column(String(1024))
639
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
640
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
641
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
642
+ scope: Mapped[Optional[InternalScope]] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
643
+ name: Mapped[Optional[str]] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
644
+ deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
645
+ __mapper_args__ = {
646
+ 'primary_key': [rse_id, path] # Fake primary key for SQLA
647
+ }
648
+ _table_args = ()
649
+
650
+
651
+ class DIDMetaConventionsKey(BASE, ModelBase):
652
+ """Represents allowed keys of DID Metadata"""
653
+ __tablename__ = 'did_keys'
654
+ key: Mapped[str] = mapped_column(String(255))
655
+ is_enum: Mapped[bool] = mapped_column(Boolean(name='DID_KEYS_IS_ENUM_CHK', create_constraint=True),
656
+ server_default='0')
657
+ key_type: Mapped[KeyType] = mapped_column(Enum(KeyType, name='DID_KEYS_TYPE_CHK',
658
+ create_constraint=True,
659
+ values_callable=lambda obj: [e.value for e in obj]))
660
+ value_type: Mapped[Optional[str]] = mapped_column(String(255))
661
+ value_regexp: Mapped[Optional[str]] = mapped_column(String(255))
662
+ _table_args = (PrimaryKeyConstraint('key', name='DID_KEYS_PK'),
663
+ CheckConstraint('key_type IS NOT NULL', name='DID_KEYS_TYPE_NN'),
664
+ CheckConstraint('is_enum IS NOT NULL', name='DID_KEYS_IS_ENUM_NN'))
665
+
666
+
667
+ class DIDMetaConventionsConstraint(BASE, ModelBase):
668
+ """Represents a map for constraint values a DID metadata key must follow """
669
+ __tablename__ = 'did_key_map'
670
+ key: Mapped[str] = mapped_column(String(255))
671
+ value: Mapped[str] = mapped_column(String(255))
672
+ _table_args = (PrimaryKeyConstraint('key', 'value', name='DID_KEY_MAP_PK'),
673
+ ForeignKeyConstraint(['key'], ['did_keys.key'], name='DID_MAP_KEYS_FK'))
674
+
675
+
676
+ class DataIdentifierAssociation(BASE, ModelBase):
677
+ """Represents the map between containers/datasets and files"""
678
+ __tablename__ = 'contents'
679
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH'))) # dataset scope
680
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH'))) # dataset name
681
+ child_scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH'))) # Provenance scope
682
+ child_name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH'))) # Provenance name
683
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='CONTENTS_DID_TYPE_CHK',
684
+ create_constraint=True,
685
+ values_callable=lambda obj: [e.value for e in obj]))
686
+ child_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='CONTENTS_CHILD_TYPE_CHK',
687
+ create_constraint=True,
688
+ values_callable=lambda obj: [e.value for e in obj]))
689
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
690
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
691
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
692
+ guid: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
693
+ events: Mapped[Optional[int]] = mapped_column(BigInteger)
694
+ rule_evaluation: Mapped[Optional[bool]] = mapped_column(Boolean(name='CONTENTS_RULE_EVALUATION_CHK', create_constraint=True))
695
+ _table_args = (PrimaryKeyConstraint('scope', 'name', 'child_scope', 'child_name', name='CONTENTS_PK'),
696
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'], name='CONTENTS_ID_FK'),
697
+ ForeignKeyConstraint(['child_scope', 'child_name'], ['dids.scope', 'dids.name'], ondelete="CASCADE", name='CONTENTS_CHILD_ID_FK'),
698
+ CheckConstraint('DID_TYPE IS NOT NULL', name='CONTENTS_DID_TYPE_NN'),
699
+ CheckConstraint('CHILD_TYPE IS NOT NULL', name='CONTENTS_CHILD_TYPE_NN'),
700
+ Index('CONTENTS_CHILD_SCOPE_NAME_IDX', 'child_scope', 'child_name', 'scope', 'name'),
701
+ Index('CONTENTS_RULE_EVAL_FB_IDX', 'rule_evaluation')) # Under Oracle this is a FB index
702
+
703
+
704
+ class ConstituentAssociation(BASE, ModelBase):
705
+ """Represents the map between archives and constituents"""
706
+ __tablename__ = 'archive_contents'
707
+ child_scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH'))) # Constituent file scope
708
+ child_name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH'))) # Constituent file name
709
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH'))) # Archive file scope
710
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH'))) # Archive file name
711
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
712
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
713
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
714
+ guid: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
715
+ length: Mapped[Optional[int]] = mapped_column(BigInteger)
716
+ _table_args = (PrimaryKeyConstraint('child_scope', 'child_name', 'scope', 'name',
717
+ name='ARCH_CONTENTS_PK'),
718
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'],
719
+ name='ARCH_CONTENTS_PARENT_FK'),
720
+ ForeignKeyConstraint(['child_scope', 'child_name'],
721
+ ['dids.scope', 'dids.name'], ondelete="CASCADE",
722
+ name='ARCH_CONTENTS_CHILD_FK'),
723
+ Index('ARCH_CONTENTS_CHILD_IDX', 'scope', 'name',
724
+ 'child_scope', 'child_name', ))
725
+
726
+
727
+ class ConstituentAssociationHistory(BASE, ModelBase):
728
+ """Represents the map history between archives and constituents"""
729
+ __tablename__ = 'archive_contents_history'
730
+ child_scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH'))) # Constituent file scope
731
+ child_name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH'))) # Constituent file name
732
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH'))) # Archive file scope
733
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH'))) # Archive file name
734
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
735
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
736
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
737
+ guid: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
738
+ length: Mapped[Optional[int]] = mapped_column(BigInteger)
739
+ __mapper_args__ = {
740
+ 'primary_key': [scope, name, child_scope, child_name] # Fake primary key for SQLA
741
+ }
742
+ _table_args = (Index('ARCH_CONT_HIST_IDX', 'scope', 'name'), )
743
+
744
+
745
+ class DataIdentifierAssociationHistory(BASE, ModelBase):
746
+ """Represents the map history between containers/datasets and files"""
747
+ __tablename__ = 'contents_history'
748
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH'))) # dataset scope
749
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH'))) # dataset name
750
+ child_scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH'))) # Provenance scope
751
+ child_name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH'))) # Provenance name
752
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='CONTENTS_HIST_DID_TYPE_CHK',
753
+ create_constraint=True,
754
+ values_callable=lambda obj: [e.value for e in obj]))
755
+ child_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='CONTENTS_HIST_CHILD_TYPE_CHK',
756
+ create_constraint=True,
757
+ values_callable=lambda obj: [e.value for e in obj]))
758
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
759
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
760
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
761
+ guid: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
762
+ events: Mapped[Optional[int]] = mapped_column(BigInteger)
763
+ rule_evaluation: Mapped[Optional[bool]] = mapped_column(Boolean(name='CONTENTS_HIST_RULE_EVAL_CHK', create_constraint=True))
764
+ did_created_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
765
+ deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
766
+ __mapper_args__ = {
767
+ 'primary_key': [scope, name, child_scope, child_name] # Fake primary key for SQLA
768
+ }
769
+ _table_args = (CheckConstraint('DID_TYPE IS NOT NULL', name='CONTENTS_HIST_DID_TYPE_NN'),
770
+ CheckConstraint('CHILD_TYPE IS NOT NULL', name='CONTENTS_HIST_CHILD_TYPE_NN'),
771
+ Index('CONTENTS_HISTORY_IDX', 'scope', 'name'))
772
+
773
+
774
+ class RSE(BASE, SoftModelBase):
775
+ """Represents a Rucio Location"""
776
+ __tablename__ = 'rses'
777
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
778
+ rse: Mapped[str] = mapped_column(String(255))
779
+ vo: Mapped[str] = mapped_column(String(3), nullable=False, server_default='def')
780
+ rse_type: Mapped[RSEType] = mapped_column(Enum(RSEType, name='RSES_TYPE_CHK',
781
+ create_constraint=True,
782
+ values_callable=lambda obj: [e.value for e in obj]),
783
+ default=RSEType.DISK)
784
+ deterministic: Mapped[bool] = mapped_column(Boolean(name='RSE_DETERMINISTIC_CHK', create_constraint=True),
785
+ default=True)
786
+ volatile: Mapped[bool] = mapped_column(Boolean(name='RSE_VOLATILE_CHK', create_constraint=True),
787
+ default=False)
788
+ staging_area: Mapped[bool] = mapped_column(Boolean(name='RSE_STAGING_AREA_CHK', create_constraint=True),
789
+ default=False)
790
+ city: Mapped[Optional[str]] = mapped_column(String(255))
791
+ region_code: Mapped[Optional[str]] = mapped_column(String(2))
792
+ country_name: Mapped[Optional[str]] = mapped_column(String(255))
793
+ continent: Mapped[Optional[str]] = mapped_column(String(2))
794
+ time_zone: Mapped[Optional[str]] = mapped_column(String(255))
795
+ ISP: Mapped[Optional[str]] = mapped_column(String(255))
796
+ ASN: Mapped[Optional[str]] = mapped_column(String(255))
797
+ longitude: Mapped[Optional[float]] = mapped_column(Float())
798
+ latitude: Mapped[Optional[float]] = mapped_column(Float())
799
+ availability: Mapped[int] = mapped_column(Integer, server_default='7') # Deprecated, will be removedx
800
+ availability_read: Mapped[bool] = mapped_column(Boolean, default=True)
801
+ availability_write: Mapped[bool] = mapped_column(Boolean, default=True)
802
+ availability_delete: Mapped[bool] = mapped_column(Boolean, default=True)
803
+ usage = relationship("RSEUsage", order_by="RSEUsage.rse_id", backref="rses")
804
+ qos_class: Mapped[Optional[str]] = mapped_column(String(64))
805
+ _table_args = (PrimaryKeyConstraint('id', name='RSES_PK'),
806
+ UniqueConstraint('rse', 'vo', name='RSES_RSE_UQ'),
807
+ CheckConstraint('RSE IS NOT NULL', name='RSES_RSE__NN'),
808
+ CheckConstraint('RSE_TYPE IS NOT NULL', name='RSES_TYPE_NN'),
809
+ ForeignKeyConstraint(['vo'], ['vos.vo'], name='RSES_VOS_FK'), )
810
+
811
+
812
+ class RSELimit(BASE, ModelBase):
813
+ """Represents RSE limits"""
814
+ __tablename__ = 'rse_limits'
815
+ rse_id: Mapped[str] = mapped_column(GUID())
816
+ name: Mapped[str] = mapped_column(String(255))
817
+ value: Mapped[int] = mapped_column(BigInteger)
818
+ _table_args = (PrimaryKeyConstraint('rse_id', 'name', name='RSE_LIMITS_PK'),
819
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='RSE_LIMIT_RSE_ID_FK'), )
820
+
821
+
822
+ class TransferLimit(BASE, ModelBase):
823
+ """Represents limits used to throttle transfer requests"""
824
+ __tablename__ = 'transfer_limits'
825
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
826
+ rse_expression: Mapped[str] = mapped_column(String(3000))
827
+ activity: Mapped[Optional[str]] = mapped_column(String(50))
828
+ direction: Mapped[TransferLimitDirection] = mapped_column(Enum(TransferLimitDirection, name='TRANSFER_LIMITS_DIRECTION_TYPE_CHK',
829
+ create_constraint=True,
830
+ values_callable=lambda obj: [e.value for e in obj]),
831
+ default=TransferLimitDirection.DESTINATION)
832
+ max_transfers: Mapped[Optional[int]] = mapped_column(BigInteger)
833
+ volume: Mapped[Optional[int]] = mapped_column(BigInteger)
834
+ deadline: Mapped[Optional[int]] = mapped_column(BigInteger)
835
+ strategy: Mapped[Optional[str]] = mapped_column(String(25))
836
+ transfers: Mapped[Optional[int]] = mapped_column(BigInteger)
837
+ waitings: Mapped[Optional[int]] = mapped_column(BigInteger)
838
+ _table_args = (PrimaryKeyConstraint('id', name='TRANSFER_LIMITS_PK'),
839
+ Index('TRANSFER_LIMITS_SELECTORS_IDX', 'rse_expression', 'activity'),
840
+ CheckConstraint('RSE_EXPRESSION IS NOT NULL', name='TRANSFER_LIMITS_RSE_EXPRESSION_NN'), )
841
+
842
+
843
+ class RSETransferLimit(BASE, ModelBase):
844
+ """Represents the binding of a transfer limit to an RSE as result of TransferLimit.rse_expression dereference"""
845
+ __tablename__ = 'rse_transfer_limits'
846
+ rse_id: Mapped[str] = mapped_column(GUID())
847
+ limit_id: Mapped[str] = mapped_column(GUID())
848
+ _table_args = (PrimaryKeyConstraint('rse_id', 'limit_id', name='RSE_TRANSFER_LIMITS_PK'),
849
+ Index('RSE_TRANSFER_LIMITS_LIMIT_ID_IDX', 'limit_id', 'rse_id'),
850
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='RSE_TRANSFER_LIMITS_RSE_ID_FK'),
851
+ ForeignKeyConstraint(['limit_id'], ['transfer_limits.id'], name='RSE_TRANSFER_LIMITS_LIMIT_ID_FK'), )
852
+
853
+
854
+ class RSEUsage(BASE, ModelBase):
855
+ """Represents location usage"""
856
+ __tablename__ = 'rse_usage'
857
+ rse_id: Mapped[str] = mapped_column(GUID())
858
+ source: Mapped[str] = mapped_column(String(255))
859
+ used: Mapped[Optional[int]] = mapped_column(BigInteger)
860
+ free: Mapped[Optional[int]] = mapped_column(BigInteger)
861
+ files: Mapped[Optional[int]] = mapped_column(BigInteger)
862
+ _table_args = (PrimaryKeyConstraint('rse_id', 'source', name='RSE_USAGE_PK'),
863
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='RSE_USAGE_RSE_ID_FK'), )
864
+
865
+
866
+ class RSEUsageHistory(BASE, ModelBase):
867
+ """Represents location usage history"""
868
+ __tablename__ = 'rse_usage_history'
869
+ rse_id: Mapped[str] = mapped_column(GUID())
870
+ source: Mapped[str] = mapped_column(String(255))
871
+ used: Mapped[Optional[int]] = mapped_column(BigInteger)
872
+ free: Mapped[Optional[int]] = mapped_column(BigInteger)
873
+ files: Mapped[Optional[int]] = mapped_column(BigInteger)
874
+ _table_args = (PrimaryKeyConstraint('rse_id', 'source', 'updated_at', name='RSE_USAGE_HISTORY_PK'), )
875
+
876
+
877
+ class UpdatedRSECounter(BASE, ModelBase):
878
+ """Represents the recently updated RSE counters"""
879
+ __tablename__ = 'updated_rse_counters'
880
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
881
+ rse_id: Mapped[str] = mapped_column(GUID())
882
+ files: Mapped[int] = mapped_column(BigInteger)
883
+ bytes: Mapped[int] = mapped_column(BigInteger)
884
+ _table_args = (PrimaryKeyConstraint('id', name='UPDATED_RSE_CNTRS_PK'),
885
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='UPDATED_RSE_CNTRS_RSE_ID_FK'),
886
+ Index('UPDATED_RSE_CNTRS_RSE_ID_IDX', 'rse_id'))
887
+
888
+
889
+ class RSEAttrAssociation(BASE, ModelBase):
890
+ """Represents the map between RSEs and tags"""
891
+ __tablename__ = 'rse_attr_map'
892
+ rse_id: Mapped[str] = mapped_column(GUID())
893
+ key: Mapped[str] = mapped_column(String(255))
894
+ value: Mapped[Optional[Union[bool, str]]] = mapped_column(BooleanString(255))
895
+ _table_args = (PrimaryKeyConstraint('rse_id', 'key', name='RSE_ATTR_MAP_PK'),
896
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='RSE_ATTR_MAP_RSE_ID_FK'),
897
+ Index('RSE_ATTR_MAP_KEY_VALUE_IDX', 'key', 'value'))
898
+
899
+
900
+ class RSEProtocol(BASE, ModelBase):
901
+ """Represents supported protocols of RSEs (Rucio Storage Elements)"""
902
+ __tablename__ = 'rse_protocols'
903
+ rse_id: Mapped[str] = mapped_column(GUID())
904
+ scheme: Mapped[str] = mapped_column(String(255))
905
+ hostname: Mapped[str] = mapped_column(String(255), server_default='') # For protocol without host e.g. POSIX on local file systems localhost is assumed as being default
906
+ port: Mapped[int] = mapped_column(Integer, server_default='0') # like host, for local protocol the port 0 is assumed to be default
907
+ prefix: Mapped[Optional[str]] = mapped_column(String(1024), nullable=True)
908
+ impl: Mapped[str] = mapped_column(String(255), nullable=False)
909
+ read_lan: Mapped[int] = mapped_column(Integer, server_default='0') # if no value is provided, 0 i.e. not supported is assumed as default value
910
+ write_lan: Mapped[int] = mapped_column(Integer, server_default='0') # if no value is provided, 0 i.e. not supported is assumed as default value
911
+ delete_lan: Mapped[int] = mapped_column(Integer, server_default='0') # if no value is provided, 0 i.e. not supported is assumed as default value
912
+ read_wan: Mapped[int] = mapped_column(Integer, server_default='0') # if no value is provided, 0 i.e. not supported is assumed as default value
913
+ write_wan: Mapped[int] = mapped_column(Integer, server_default='0') # if no value is provided, 0 i.e. not supported is assumed as default value
914
+ delete_wan: Mapped[int] = mapped_column(Integer, server_default='0') # if no value is provided, 0 i.e. not supported is assumed as default value
915
+ third_party_copy_read: Mapped[int] = mapped_column(Integer, server_default='0') # if no value is provided, 0 i.e. not supported is assumed as default value
916
+ third_party_copy_write: Mapped[int] = mapped_column(Integer, server_default='0') # if no value is provided, 0 i.e. not supported is assumed as default value
917
+ extended_attributes: Mapped[Optional[str]] = mapped_column(String(4000), nullable=True)
918
+ _table_args = (PrimaryKeyConstraint('rse_id', 'scheme', 'hostname', 'port', name='RSE_PROTOCOL_PK'),
919
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='RSE_PROTOCOL_RSE_ID_FK'),
920
+ CheckConstraint('IMPL IS NOT NULL', name='RSE_PROTOCOLS_IMPL_NN'))
921
+
922
+
923
+ class RSEQoSAssociation(BASE, ModelBase):
924
+ """Represents the mapping of RSEs"""
925
+ __tablename__ = 'rse_qos_map'
926
+ rse_id: Mapped[str] = mapped_column(GUID())
927
+ qos_policy: Mapped[str] = mapped_column(String(64))
928
+ _table_args = (PrimaryKeyConstraint('rse_id', 'qos_policy', name='RSE_QOS_MAP_PK'),
929
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='RSE_QOS_MAP_RSE_ID_FK'))
930
+
931
+
932
+ class AccountLimit(BASE, ModelBase):
933
+ """Represents account limits"""
934
+ __tablename__ = 'account_limits'
935
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
936
+ rse_id: Mapped[str] = mapped_column(GUID())
937
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
938
+ _table_args = (PrimaryKeyConstraint('account', 'rse_id', name='ACCOUNT_LIMITS_PK'),
939
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='ACCOUNT_LIMITS_ACCOUNT_FK'),
940
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='ACCOUNT_LIMITS_RSE_ID_FK'),)
941
+
942
+
943
+ class AccountGlobalLimit(BASE, ModelBase):
944
+ """Represents account limits"""
945
+ __tablename__ = 'account_glob_limits'
946
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
947
+ rse_expression: Mapped[str] = mapped_column(String(3000))
948
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
949
+ _table_args = (PrimaryKeyConstraint('account', 'rse_expression', name='ACCOUNT_GLOBAL_LIMITS_PK'),
950
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='ACCOUNT_GLOBAL_LIMITS_ACC_FK'),)
951
+
952
+
953
+ class AccountUsage(BASE, ModelBase):
954
+ """Represents account usage"""
955
+ __tablename__ = 'account_usage'
956
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
957
+ rse_id: Mapped[str] = mapped_column(GUID())
958
+ files: Mapped[int] = mapped_column(BigInteger)
959
+ bytes: Mapped[int] = mapped_column(BigInteger)
960
+ _table_args = (PrimaryKeyConstraint('account', 'rse_id', name='ACCOUNT_USAGE_PK'),
961
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='ACCOUNT_USAGE_ACCOUNT_FK'),
962
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='ACCOUNT_USAGE_RSES_ID_FK'), )
963
+
964
+
965
+ class AccountUsageHistory(BASE, ModelBase):
966
+ """Represents account usage history"""
967
+ __tablename__ = 'account_usage_history'
968
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
969
+ rse_id: Mapped[str] = mapped_column(GUID())
970
+ files: Mapped[int] = mapped_column(BigInteger)
971
+ bytes: Mapped[int] = mapped_column(BigInteger)
972
+ _table_args = (PrimaryKeyConstraint('account', 'rse_id', 'updated_at', name='ACCOUNT_USAGE_HISTORY_PK'),)
973
+
974
+
975
+ class RSEFileAssociation(BASE, ModelBase):
976
+ """Represents the map between locations and files"""
977
+ __tablename__ = 'replicas'
978
+ rse_id: Mapped[str] = mapped_column(GUID())
979
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
980
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
981
+ bytes: Mapped[int] = mapped_column(BigInteger)
982
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
983
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
984
+ path: Mapped[Optional[str]] = mapped_column(String(1024))
985
+ state: Mapped[ReplicaState] = mapped_column(Enum(ReplicaState, name='REPLICAS_STATE_CHK',
986
+ create_constraint=True,
987
+ values_callable=lambda obj: [e.value for e in obj]),
988
+ default=ReplicaState.UNAVAILABLE)
989
+ lock_cnt: Mapped[int] = mapped_column(Integer, server_default='0')
990
+ accessed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
991
+ tombstone: Mapped[Optional[datetime]] = mapped_column(DateTime)
992
+ _table_args = (PrimaryKeyConstraint('scope', 'name', 'rse_id', name='REPLICAS_PK'),
993
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'], name='REPLICAS_LFN_FK'),
994
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='REPLICAS_RSE_ID_FK'),
995
+ CheckConstraint('STATE IS NOT NULL', name='REPLICAS_STATE_NN'),
996
+ CheckConstraint('bytes IS NOT NULL', name='REPLICAS_SIZE_NN'),
997
+ CheckConstraint('lock_cnt IS NOT NULL', name='REPLICAS_LOCK_CNT_NN'),
998
+ Index('REPLICAS_PATH_IDX', 'path', mysql_length=common_schema.get_schema_value('NAME_LENGTH')),
999
+ Index('REPLICAS_STATE_IDX', 'state'),
1000
+ Index('REPLICAS_RSE_ID_TOMBSTONE_IDX', 'rse_id', 'tombstone'))
1001
+
1002
+
1003
+ class CollectionReplica(BASE, ModelBase):
1004
+ """Represents replicas for datasets/collections"""
1005
+ __tablename__ = 'collection_replicas'
1006
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1007
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1008
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='COLLECTION_REPLICAS_TYPE_CHK',
1009
+ create_constraint=True,
1010
+ values_callable=lambda obj: [e.value for e in obj]))
1011
+ rse_id: Mapped[str] = mapped_column(GUID())
1012
+ bytes: Mapped[int] = mapped_column(BigInteger)
1013
+ length: Mapped[int] = mapped_column(BigInteger)
1014
+ available_bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
1015
+ available_replicas_cnt: Mapped[Optional[int]] = mapped_column(BigInteger)
1016
+ state: Mapped[ReplicaState] = mapped_column(Enum(ReplicaState, name='COLLECTION_REPLICAS_STATE_CHK',
1017
+ create_constraint=True,
1018
+ values_callable=lambda obj: [e.value for e in obj]),
1019
+ default=ReplicaState.UNAVAILABLE)
1020
+ accessed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1021
+ _table_args = (PrimaryKeyConstraint('scope', 'name', 'rse_id', name='COLLECTION_REPLICAS_PK'),
1022
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'], name='COLLECTION_REPLICAS_LFN_FK'),
1023
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='COLLECTION_REPLICAS_RSE_ID_FK'),
1024
+ CheckConstraint('STATE IS NOT NULL', name='COLLECTION_REPLICAS_STATE_NN'),
1025
+ CheckConstraint('bytes IS NOT NULL', name='COLLECTION_REPLICAS_SIZE_NN'),
1026
+ Index('COLLECTION_REPLICAS_RSE_ID_IDX', 'rse_id'))
1027
+
1028
+
1029
+ class UpdatedCollectionReplica(BASE, ModelBase):
1030
+ """Represents updates to replicas for datasets/collections"""
1031
+ __tablename__ = 'updated_col_rep'
1032
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1033
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1034
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1035
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='UPDATED_COL_REP_TYPE_CHK',
1036
+ create_constraint=True,
1037
+ values_callable=lambda obj: [e.value for e in obj]))
1038
+ rse_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1039
+ _table_args = (PrimaryKeyConstraint('id', name='UPDATED_COL_REP_PK'),
1040
+ CheckConstraint('SCOPE IS NOT NULL', name='UPDATED_COL_REP_SCOPE_NN'),
1041
+ CheckConstraint('NAME IS NOT NULL', name='UPDATED_COL_REP_NAME_NN'),
1042
+ Index('UPDATED_COL_REP_SNR_IDX', 'scope', 'name', 'rse_id'))
1043
+
1044
+
1045
+ class RSEFileAssociationHistory(BASE, ModelBase):
1046
+ """Represents a short history of the deleted replicas"""
1047
+ __tablename__ = 'replicas_history'
1048
+ rse_id: Mapped[str] = mapped_column(GUID())
1049
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1050
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1051
+ bytes: Mapped[int] = mapped_column(BigInteger)
1052
+ _table_args = (PrimaryKeyConstraint('rse_id', 'scope', 'name', name='REPLICAS_HIST_PK'),
1053
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='REPLICAS_HIST_RSE_ID_FK'),
1054
+ CheckConstraint('bytes IS NOT NULL', name='REPLICAS_HIST_SIZE_NN'))
1055
+
1056
+
1057
+ class ReplicationRule(BASE, ModelBase):
1058
+ """Represents data identifier replication rules"""
1059
+ __tablename__ = 'rules'
1060
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1061
+ subscription_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1062
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1063
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1064
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1065
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='RULES_DID_TYPE_CHK',
1066
+ create_constraint=True,
1067
+ values_callable=lambda obj: [e.value for e in obj]))
1068
+ state: Mapped[RuleState] = mapped_column(Enum(RuleState, name='RULES_STATE_CHK',
1069
+ create_constraint=True,
1070
+ values_callable=lambda obj: [e.value for e in obj]),
1071
+ default=RuleState.REPLICATING)
1072
+ error: Mapped[Optional[str]] = mapped_column(String(255))
1073
+ rse_expression: Mapped[str] = mapped_column(String(3000))
1074
+ copies: Mapped[int] = mapped_column(SmallInteger, server_default='1')
1075
+ expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1076
+ weight: Mapped[Optional[str]] = mapped_column(String(255))
1077
+ locked: Mapped[bool] = mapped_column(Boolean(name='RULES_LOCKED_CHK', create_constraint=True),
1078
+ default=False)
1079
+ locks_ok_cnt: Mapped[int] = mapped_column(BigInteger, server_default='0')
1080
+ locks_replicating_cnt: Mapped[int] = mapped_column(BigInteger, server_default='0')
1081
+ locks_stuck_cnt: Mapped[int] = mapped_column(BigInteger, server_default='0')
1082
+ source_replica_expression: Mapped[Optional[str]] = mapped_column(String(255))
1083
+ activity: Mapped[Optional[str]] = mapped_column(String(50), default='default')
1084
+ grouping: Mapped[RuleGrouping] = mapped_column(Enum(RuleGrouping, name='RULES_GROUPING_CHK',
1085
+ create_constraint=True,
1086
+ values_callable=lambda obj: [e.value for e in obj]),
1087
+ default=RuleGrouping.ALL)
1088
+ notification: Mapped[RuleNotification] = mapped_column(Enum(RuleNotification, name='RULES_NOTIFICATION_CHK',
1089
+ create_constraint=True,
1090
+ values_callable=lambda obj: [e.value for e in obj]),
1091
+ default=RuleNotification.NO)
1092
+ stuck_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1093
+ purge_replicas: Mapped[bool] = mapped_column(Boolean(name='RULES_PURGE_REPLICAS_CHK', create_constraint=True),
1094
+ default=False)
1095
+ ignore_availability: Mapped[bool] = mapped_column(Boolean(name='RULES_IGNORE_AVAILABILITY_CHK', create_constraint=True),
1096
+ default=False)
1097
+ ignore_account_limit: Mapped[bool] = mapped_column(Boolean(name='RULES_IGNORE_ACCOUNT_LIMIT_CHK', create_constraint=True),
1098
+ default=False)
1099
+ priority: Mapped[Optional[int]] = mapped_column(Integer)
1100
+ comments: Mapped[Optional[str]] = mapped_column(String(255))
1101
+ child_rule_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1102
+ eol_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1103
+ split_container: Mapped[bool] = mapped_column(Boolean(name='RULES_SPLIT_CONTAINER_CHK', create_constraint=True),
1104
+ default=False)
1105
+ meta: Mapped[Optional[str]] = mapped_column(String(4000))
1106
+ _table_args = (PrimaryKeyConstraint('id', name='RULES_PK'),
1107
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'], name='RULES_SCOPE_NAME_FK'),
1108
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='RULES_ACCOUNT_FK'),
1109
+ ForeignKeyConstraint(['subscription_id'], ['subscriptions.id'], name='RULES_SUBS_ID_FK'),
1110
+ ForeignKeyConstraint(['child_rule_id'], ['rules.id'], name='RULES_CHILD_RULE_ID_FK'),
1111
+ CheckConstraint('STATE IS NOT NULL', name='RULES_STATE_NN'),
1112
+ CheckConstraint('SCOPE IS NOT NULL', name='RULES_SCOPE_NN'),
1113
+ CheckConstraint('NAME IS NOT NULL', name='RULES_NAME_NN'),
1114
+ CheckConstraint(grouping != None, name='RULES_GROUPING_NN'), # NOQA: E711
1115
+ CheckConstraint('COPIES IS NOT NULL', name='RULES_COPIES_NN'),
1116
+ CheckConstraint('LOCKED IS NOT NULL', name='RULES_LOCKED_NN'),
1117
+ CheckConstraint('ACCOUNT IS NOT NULL', name='RULES_ACCOUNT_NN'),
1118
+ CheckConstraint('LOCKS_OK_CNT IS NOT NULL', name='RULES_LOCKS_OK_CNT_NN'),
1119
+ CheckConstraint('LOCKS_REPLICATING_CNT IS NOT NULL', name='RULES_LOCKS_REPLICATING_CNT_NN'),
1120
+ CheckConstraint('LOCKS_STUCK_CNT IS NOT NULL', name='RULES_LOCKS_STUCK_CNT_NN'),
1121
+ CheckConstraint('PURGE_REPLICAS IS NOT NULL', name='RULES_PURGE_REPLICAS_NN'),
1122
+ Index('RULES_SC_NA_AC_RS_CO_UQ_IDX', 'scope', 'name', 'account', 'rse_expression', 'copies',
1123
+ unique=True, mysql_length={'rse_expression': 767}),
1124
+ Index('RULES_SCOPE_NAME_IDX', 'scope', 'name'),
1125
+ Index('RULES_EXPIRES_AT_IDX', 'expires_at'),
1126
+ Index('RULES_STATE_IDX', 'state'),
1127
+ Index('RULES_CHILD_RULE_ID_IDX', 'child_rule_id'))
1128
+
1129
+
1130
+ class ReplicationRuleHistoryRecent(BASE, ModelBase):
1131
+ """Represents replication rules in the recent history"""
1132
+ __tablename__ = 'rules_hist_recent'
1133
+ id: Mapped[str] = mapped_column(GUID())
1134
+ subscription_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1135
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1136
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1137
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1138
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='RULES_HIST_RECENT_DIDTYPE_CHK',
1139
+ create_constraint=True,
1140
+ values_callable=lambda obj: [e.value for e in obj]))
1141
+ state: Mapped[RuleState] = mapped_column(Enum(RuleState, name='RULES_HIST_RECENT_STATE_CHK',
1142
+ create_constraint=True,
1143
+ values_callable=lambda obj: [e.value for e in obj]))
1144
+ error: Mapped[Optional[str]] = mapped_column(String(255))
1145
+ rse_expression: Mapped[str] = mapped_column(String(3000))
1146
+ copies: Mapped[Optional[int]] = mapped_column(SmallInteger)
1147
+ expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1148
+ weight: Mapped[Optional[str]] = mapped_column(String(255))
1149
+ locked: Mapped[bool] = mapped_column(Boolean())
1150
+ locks_ok_cnt: Mapped[Optional[int]] = mapped_column(BigInteger)
1151
+ locks_replicating_cnt: Mapped[int] = mapped_column(BigInteger)
1152
+ locks_stuck_cnt: Mapped[Optional[int]] = mapped_column(BigInteger)
1153
+ source_replica_expression: Mapped[Optional[str]] = mapped_column(String(255))
1154
+ activity: Mapped[Optional[str]] = mapped_column(String(50))
1155
+ grouping: Mapped[RuleGrouping] = mapped_column(Enum(RuleGrouping, name='RULES_HIST_RECENT_GROUPING_CHK',
1156
+ create_constraint=True,
1157
+ values_callable=lambda obj: [e.value for e in obj]))
1158
+ notification: Mapped[RuleNotification] = mapped_column(Enum(RuleNotification, name='RULES_HIST_RECENT_NOTIFY_CHK',
1159
+ create_constraint=True,
1160
+ values_callable=lambda obj: [e.value for e in obj]))
1161
+ stuck_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1162
+ purge_replicas: Mapped[bool] = mapped_column(Boolean())
1163
+ ignore_availability: Mapped[bool] = mapped_column(Boolean())
1164
+ ignore_account_limit: Mapped[bool] = mapped_column(Boolean())
1165
+ priority: Mapped[Optional[int]] = mapped_column(Integer)
1166
+ comments: Mapped[Optional[str]] = mapped_column(String(255))
1167
+ child_rule_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1168
+ eol_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1169
+ split_container: Mapped[bool] = mapped_column(Boolean())
1170
+ meta: Mapped[Optional[str]] = mapped_column(String(4000))
1171
+ __mapper_args__ = {
1172
+ 'primary_key': [id, locks_replicating_cnt] # Fake primary key for SQLA
1173
+ }
1174
+ _table_args = (Index('RULES_HIST_RECENT_ID_IDX', 'id'),
1175
+ Index('RULES_HIST_RECENT_SC_NA_IDX', 'scope', 'name'))
1176
+
1177
+
1178
+ class ReplicationRuleHistory(BASE, ModelBase):
1179
+ """Represents replication rules in the longterm history"""
1180
+ __tablename__ = 'rules_history'
1181
+ id: Mapped[str] = mapped_column(GUID())
1182
+ subscription_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1183
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1184
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1185
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1186
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='RULES_HISTORY_DIDTYPE_CHK',
1187
+ create_constraint=True,
1188
+ values_callable=lambda obj: [e.value for e in obj]))
1189
+ state: Mapped[RuleState] = mapped_column(Enum(RuleState, name='RULES_HISTORY_STATE_CHK',
1190
+ create_constraint=True,
1191
+ values_callable=lambda obj: [e.value for e in obj]))
1192
+ error: Mapped[Optional[str]] = mapped_column(String(255))
1193
+ rse_expression: Mapped[str] = mapped_column(String(3000))
1194
+ copies: Mapped[Optional[int]] = mapped_column(SmallInteger)
1195
+ expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1196
+ weight: Mapped[Optional[str]] = mapped_column(String(255))
1197
+ locked: Mapped[bool] = mapped_column(Boolean())
1198
+ locks_ok_cnt: Mapped[Optional[int]] = mapped_column(BigInteger)
1199
+ locks_replicating_cnt: Mapped[int] = mapped_column(BigInteger)
1200
+ locks_stuck_cnt: Mapped[Optional[int]] = mapped_column(BigInteger)
1201
+ source_replica_expression: Mapped[Optional[str]] = mapped_column(String(255))
1202
+ activity: Mapped[Optional[str]] = mapped_column(String(50))
1203
+ grouping: Mapped[RuleGrouping] = mapped_column(Enum(RuleGrouping, name='RULES_HISTORY_GROUPING_CHK',
1204
+ create_constraint=True,
1205
+ values_callable=lambda obj: [e.value for e in obj]))
1206
+ notification: Mapped[RuleNotification] = mapped_column(Enum(RuleNotification, name='RULES_HISTORY_NOTIFY_CHK',
1207
+ create_constraint=True,
1208
+ values_callable=lambda obj: [e.value for e in obj]))
1209
+ stuck_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1210
+ priority: Mapped[Optional[int]] = mapped_column(Integer)
1211
+ purge_replicas: Mapped[bool] = mapped_column(Boolean())
1212
+ ignore_availability: Mapped[bool] = mapped_column(Boolean())
1213
+ ignore_account_limit: Mapped[bool] = mapped_column(Boolean())
1214
+ comments: Mapped[Optional[str]] = mapped_column(String(255))
1215
+ child_rule_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1216
+ eol_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1217
+ split_container: Mapped[bool] = mapped_column(Boolean())
1218
+ meta: Mapped[Optional[str]] = mapped_column(String(4000))
1219
+ __mapper_args__ = {
1220
+ 'primary_key': [id, locks_replicating_cnt] # Fake primary key for SQLA
1221
+ }
1222
+ _table_args = (Index('RULES_HISTORY_SCOPENAME_IDX', 'scope', 'name'), )
1223
+
1224
+
1225
+ class ReplicaLock(BASE, ModelBase):
1226
+ """Represents replica locks"""
1227
+ __tablename__ = 'locks'
1228
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1229
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1230
+ rule_id: Mapped[str] = mapped_column(GUID())
1231
+ rse_id: Mapped[str] = mapped_column(GUID())
1232
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1233
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
1234
+ state: Mapped[LockState] = mapped_column(Enum(LockState, name='LOCKS_STATE_CHK',
1235
+ create_constraint=True,
1236
+ values_callable=lambda obj: [e.value for e in obj]),
1237
+ default=LockState.REPLICATING)
1238
+ repair_cnt: Mapped[Optional[int]] = mapped_column(BigInteger)
1239
+ _table_args = (PrimaryKeyConstraint('scope', 'name', 'rule_id', 'rse_id', name='LOCKS_PK'),
1240
+ ForeignKeyConstraint(['rule_id'], ['rules.id'], name='LOCKS_RULE_ID_FK'),
1241
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='LOCKS_ACCOUNT_FK'),
1242
+ CheckConstraint('STATE IS NOT NULL', name='LOCKS_STATE_NN'),
1243
+ CheckConstraint('ACCOUNT IS NOT NULL', name='LOCKS_ACCOUNT_NN'),
1244
+ Index('LOCKS_RULE_ID_IDX', 'rule_id'))
1245
+
1246
+
1247
+ class DatasetLock(BASE, ModelBase):
1248
+ """Represents dataset locks"""
1249
+ __tablename__ = 'dataset_locks'
1250
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1251
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1252
+ rule_id: Mapped[str] = mapped_column(GUID())
1253
+ rse_id: Mapped[str] = mapped_column(GUID())
1254
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1255
+ state: Mapped[LockState] = mapped_column(Enum(LockState, name='DATASET_LOCKS_STATE_CHK',
1256
+ create_constraint=True,
1257
+ values_callable=lambda obj: [e.value for e in obj]),
1258
+ default=LockState.REPLICATING)
1259
+ length: Mapped[Optional[int]] = mapped_column(BigInteger)
1260
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
1261
+ accessed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1262
+ _table_args = (PrimaryKeyConstraint('scope', 'name', 'rule_id', 'rse_id', name='DATASET_LOCKS_PK'),
1263
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'], name='DATASET_LOCKS_DID_FK'),
1264
+ ForeignKeyConstraint(['rule_id'], ['rules.id'], name='DATASET_LOCKS_RULE_ID_FK'),
1265
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='DATASET_LOCKS_ACCOUNT_FK'),
1266
+ CheckConstraint('STATE IS NOT NULL', name='DATASET_LOCKS_STATE_NN'),
1267
+ CheckConstraint('ACCOUNT IS NOT NULL', name='DATASET_LOCKS_ACCOUNT_NN'),
1268
+ Index('DATASET_LOCKS_RULE_ID_IDX', 'rule_id'),
1269
+ Index('DATASET_LOCKS_RSE_ID_IDX', 'rse_id'))
1270
+
1271
+
1272
+ class UpdatedAccountCounter(BASE, ModelBase):
1273
+ """Represents the recently updated Account counters"""
1274
+ __tablename__ = 'updated_account_counters'
1275
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1276
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1277
+ rse_id: Mapped[str] = mapped_column(GUID())
1278
+ files: Mapped[int] = mapped_column(BigInteger)
1279
+ bytes: Mapped[int] = mapped_column(BigInteger)
1280
+ _table_args = (PrimaryKeyConstraint('id', name='UPDATED_ACCNT_CNTRS_PK'),
1281
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='UPDATED_ACCNT_CNTRS_RSE_ID_FK'),
1282
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='UPDATED_ACCNT_CNTRS_ACCOUNT_FK'),
1283
+ Index('UPDATED_ACCNT_CNTRS_RSE_ID_IDX', 'account', 'rse_id'))
1284
+
1285
+
1286
+ class Request(BASE, ModelBase):
1287
+ """Represents a request for a single file with a third party service"""
1288
+ __tablename__ = 'requests'
1289
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1290
+ request_type: Mapped[RequestType] = mapped_column(Enum(RequestType, name='REQUESTS_TYPE_CHK',
1291
+ create_constraint=True,
1292
+ values_callable=lambda obj: [e.value for e in obj]),
1293
+ default=RequestType.TRANSFER)
1294
+ scope: Mapped[Optional[InternalScope]] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1295
+ name: Mapped[Optional[str]] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1296
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='REQUESTS_DIDTYPE_CHK',
1297
+ create_constraint=True,
1298
+ values_callable=lambda obj: [e.value for e in obj]),
1299
+ default=DIDType.FILE)
1300
+ dest_rse_id: Mapped[str] = mapped_column(GUID())
1301
+ source_rse_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1302
+ attributes: Mapped[Optional[str]] = mapped_column(String(4000))
1303
+ state: Mapped[RequestState] = mapped_column(Enum(RequestState, name='REQUESTS_STATE_CHK',
1304
+ create_constraint=True,
1305
+ values_callable=lambda obj: [e.value for e in obj]),
1306
+ default=RequestState.QUEUED)
1307
+ external_id: Mapped[Optional[str]] = mapped_column(String(64))
1308
+ external_host: Mapped[Optional[str]] = mapped_column(String(256))
1309
+ retry_count: Mapped[int] = mapped_column(Integer(), server_default='0')
1310
+ err_msg: Mapped[Optional[str]] = mapped_column(String(4000))
1311
+ previous_attempt_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1312
+ rule_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1313
+ activity: Mapped[Optional[str]] = mapped_column(String(50), default='default')
1314
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
1315
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
1316
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
1317
+ dest_url: Mapped[Optional[str]] = mapped_column(String(2048))
1318
+ submitted_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1319
+ started_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1320
+ transferred_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1321
+ estimated_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1322
+ submitter_id: Mapped[Optional[int]] = mapped_column(Integer)
1323
+ estimated_started_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1324
+ estimated_transferred_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1325
+ staging_started_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1326
+ staging_finished_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1327
+ account: Mapped[Optional[InternalAccount]] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1328
+ requested_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1329
+ last_processed_by: Mapped[Optional[str]] = mapped_column(String(64))
1330
+ last_processed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1331
+ priority: Mapped[Optional[int]] = mapped_column(Integer)
1332
+ transfertool: Mapped[Optional[str]] = mapped_column(String(64))
1333
+ _table_args = (PrimaryKeyConstraint('id', name='REQUESTS_PK'),
1334
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'], name='REQUESTS_DID_FK'),
1335
+ ForeignKeyConstraint(['dest_rse_id'], ['rses.id'], name='REQUESTS_RSES_FK'),
1336
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='REQUESTS_ACCOUNT_FK'),
1337
+ CheckConstraint('dest_rse_id IS NOT NULL', name='REQUESTS_RSE_ID_NN'),
1338
+ Index('REQUESTS_SCOPE_NAME_RSE_IDX', 'scope', 'name', 'dest_rse_id', 'request_type'),
1339
+ Index('REQUESTS_TYP_STA_UPD_IDX_OLD', 'request_type', 'state', 'updated_at'),
1340
+ Index('REQUESTS_TYP_STA_UPD_IDX', 'request_type', 'state', 'activity'),
1341
+ Index('REQUESTS_RULEID_IDX', 'rule_id'),
1342
+ Index('REQUESTS_EXTERNALID_UQ', 'external_id'),
1343
+ Index('REQUESTS_DEST_RSE_ID_IDX', 'dest_rse_id'),
1344
+ Index('REQUESTS_TYP_STA_TRA_ACT_IDX', 'request_type', 'state', 'transfertool', 'activity'))
1345
+
1346
+
1347
+ class TransferHop(BASE, ModelBase):
1348
+ """Represents source files for transfers"""
1349
+ __tablename__ = 'transfer_hops'
1350
+ request_id: Mapped[str] = mapped_column(GUID())
1351
+ next_hop_request_id: Mapped[str] = mapped_column(GUID())
1352
+ initial_request_id: Mapped[str] = mapped_column(GUID())
1353
+ _table_args = (PrimaryKeyConstraint('request_id', 'next_hop_request_id', 'initial_request_id', name='TRANSFER_HOPS_PK'),
1354
+ ForeignKeyConstraint(['initial_request_id'], ['requests.id'], name='TRANSFER_HOPS_INIT_REQ_ID_FK'),
1355
+ ForeignKeyConstraint(['request_id'], ['requests.id'], name='TRANSFER_HOPS_REQ_ID_FK'),
1356
+ ForeignKeyConstraint(['next_hop_request_id'], ['requests.id'], name='TRANSFER_HOPS_NH_REQ_ID_FK'),
1357
+ Index('TRANSFER_HOPS_INITIAL_REQ_IDX', 'initial_request_id'),
1358
+ Index('TRANSFER_HOPS_NH_REQ_IDX', 'next_hop_request_id'))
1359
+
1360
+
1361
+ class RequestHistory(BASE, ModelBase):
1362
+ """Represents request history"""
1363
+ __tablename__ = 'requests_history'
1364
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1365
+ request_type: Mapped[RequestType] = mapped_column(Enum(RequestType, name='REQUESTS_HIST_TYPE_CHK',
1366
+ create_constraint=True,
1367
+ values_callable=lambda obj: [e.value for e in obj]),
1368
+ default=RequestType.TRANSFER)
1369
+ scope: Mapped[Optional[InternalScope]] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1370
+ name: Mapped[Optional[str]] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1371
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='REQUESTS_HIST_DIDTYPE_CHK',
1372
+ create_constraint=True,
1373
+ values_callable=lambda obj: [e.value for e in obj]),
1374
+ default=DIDType.FILE)
1375
+ dest_rse_id: Mapped[str] = mapped_column(GUID())
1376
+ source_rse_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1377
+ attributes: Mapped[Optional[str]] = mapped_column(String(4000))
1378
+ state: Mapped[RequestState] = mapped_column(Enum(RequestState, name='REQUESTS_HIST_STATE_CHK',
1379
+ create_constraint=True,
1380
+ values_callable=lambda obj: [e.value for e in obj]),
1381
+ default=RequestState.QUEUED)
1382
+ external_id: Mapped[Optional[str]] = mapped_column(String(64))
1383
+ external_host: Mapped[Optional[str]] = mapped_column(String(256))
1384
+ retry_count: Mapped[int] = mapped_column(Integer(), server_default='0')
1385
+ err_msg: Mapped[Optional[str]] = mapped_column(String(4000))
1386
+ previous_attempt_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1387
+ rule_id: Mapped[Optional[uuid.UUID]] = mapped_column(GUID())
1388
+ activity: Mapped[Optional[str]] = mapped_column(String(50), default='default')
1389
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
1390
+ md5: Mapped[Optional[str]] = mapped_column(String(32))
1391
+ adler32: Mapped[Optional[str]] = mapped_column(String(8))
1392
+ dest_url: Mapped[Optional[str]] = mapped_column(String(2048))
1393
+ submitted_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1394
+ started_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1395
+ transferred_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1396
+ estimated_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1397
+ submitter_id: Mapped[Optional[int]] = mapped_column(Integer)
1398
+ estimated_started_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1399
+ estimated_transferred_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1400
+ staging_started_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1401
+ staging_finished_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1402
+ account: Mapped[Optional[InternalAccount]] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1403
+ requested_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1404
+ priority: Mapped[Optional[int]] = mapped_column(Integer)
1405
+ transfertool: Mapped[Optional[str]] = mapped_column(String(64))
1406
+ __mapper_args__ = {
1407
+ 'primary_key': [id] # Fake primary key for SQLA
1408
+ }
1409
+ _table_args = (Index('REQ_HIST_SCOPE_NAME_RSE_IDX', 'scope', 'name', 'dest_rse_id'),
1410
+ )
1411
+
1412
+
1413
+ class Source(BASE, ModelBase):
1414
+ """Represents source files for transfers"""
1415
+ __tablename__ = 'sources'
1416
+ request_id: Mapped[str] = mapped_column(GUID())
1417
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1418
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1419
+ rse_id: Mapped[str] = mapped_column(GUID())
1420
+ dest_rse_id: Mapped[str] = mapped_column(GUID())
1421
+ url: Mapped[Optional[str]] = mapped_column(String(2048))
1422
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
1423
+ ranking: Mapped[Optional[int]] = mapped_column(Integer())
1424
+ is_using: Mapped[bool] = mapped_column(Boolean(), default=False)
1425
+ _table_args = (PrimaryKeyConstraint('request_id', 'rse_id', 'scope', 'name', name='SOURCES_PK'),
1426
+ ForeignKeyConstraint(['request_id'], ['requests.id'], name='SOURCES_REQ_ID_FK'),
1427
+ ForeignKeyConstraint(['scope', 'name', 'rse_id'], ['replicas.scope', 'replicas.name', 'replicas.rse_id'], name='SOURCES_REPLICA_FK'),
1428
+ ForeignKeyConstraint(['rse_id'], ['rses.id'], name='SOURCES_RSES_FK'),
1429
+ ForeignKeyConstraint(['dest_rse_id'], ['rses.id'], name='SOURCES_DEST_RSES_FK'),
1430
+ Index('SOURCES_SRC_DST_IDX', 'rse_id', 'dest_rse_id'),
1431
+ Index('SOURCES_SC_NM_DST_IDX', 'scope', 'rse_id', 'name'),
1432
+ Index('SOURCES_DEST_RSEID_IDX', 'dest_rse_id'))
1433
+
1434
+
1435
+ class SourceHistory(BASE, ModelBase):
1436
+ """Represents history of source files for transfers"""
1437
+ __tablename__ = 'sources_history'
1438
+ request_id: Mapped[str] = mapped_column(GUID())
1439
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1440
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1441
+ rse_id: Mapped[str] = mapped_column(GUID())
1442
+ dest_rse_id: Mapped[str] = mapped_column(GUID())
1443
+ url: Mapped[Optional[str]] = mapped_column(String(2048))
1444
+ bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
1445
+ ranking: Mapped[Optional[int]] = mapped_column(Integer())
1446
+ is_using: Mapped[bool] = mapped_column(Boolean(), default=False)
1447
+ __mapper_args__ = {
1448
+ 'primary_key': [request_id] # Fake primary key for SQLA
1449
+ }
1450
+ _table_args = (Index('SOURCES_HIST_REQID_IDX', 'request_id'),
1451
+ )
1452
+
1453
+
1454
+ class Distance(BASE, ModelBase):
1455
+ """Represents distance between rses"""
1456
+ __tablename__ = 'distances'
1457
+ src_rse_id: Mapped[str] = mapped_column(GUID())
1458
+ dest_rse_id: Mapped[str] = mapped_column(GUID())
1459
+ distance: Mapped[Optional[int]] = mapped_column(Integer())
1460
+ _table_args = (PrimaryKeyConstraint('src_rse_id', 'dest_rse_id', name='DISTANCES_PK'),
1461
+ ForeignKeyConstraint(['src_rse_id'], ['rses.id'], name='DISTANCES_SRC_RSES_FK'),
1462
+ ForeignKeyConstraint(['dest_rse_id'], ['rses.id'], name='DISTANCES_DEST_RSES_FK'),
1463
+ Index('DISTANCES_DEST_RSEID_IDX', 'dest_rse_id'))
1464
+
1465
+
1466
+ class TransferStats(BASE, ModelBase):
1467
+ """Represents counters for transfer link usage"""
1468
+ __tablename__ = 'transfer_stats'
1469
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1470
+ resolution: Mapped[int] = mapped_column(Integer)
1471
+ timestamp: Mapped[datetime] = mapped_column(DateTime)
1472
+ dest_rse_id: Mapped[str] = mapped_column(GUID())
1473
+ src_rse_id: Mapped[str] = mapped_column(GUID())
1474
+ activity: Mapped[Optional[str]] = mapped_column(String(50))
1475
+ files_done: Mapped[int] = mapped_column(BigInteger)
1476
+ bytes_done: Mapped[int] = mapped_column(BigInteger)
1477
+ files_failed: Mapped[int] = mapped_column(BigInteger)
1478
+ _table_args = (PrimaryKeyConstraint('id', name='TRANSFER_STATS_PK'),
1479
+ ForeignKeyConstraint(['dest_rse_id'], ['rses.id'], name='TRANSFER_STATS_DEST_RSE_FK'),
1480
+ ForeignKeyConstraint(['src_rse_id'], ['rses.id'], name='TRANSFER_STATS_SRC_RSE_FK'),
1481
+ Index('TRANSFER_STATS_KEY_IDX', 'resolution', 'timestamp', 'dest_rse_id', 'src_rse_id', 'activity'))
1482
+
1483
+
1484
+ class Subscription(BASE, ModelBase):
1485
+ """Represents a subscription"""
1486
+ __tablename__ = 'subscriptions'
1487
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1488
+ name: Mapped[str] = mapped_column(String(64))
1489
+ filter: Mapped[Optional[str]] = mapped_column(String(4000))
1490
+ replication_rules: Mapped[Optional[str]] = mapped_column(String(4000))
1491
+ policyid: Mapped[int] = mapped_column(SmallInteger, server_default='0')
1492
+ state: Mapped[SubscriptionState] = mapped_column(Enum(SubscriptionState, name='SUBSCRIPTIONS_STATE_CHK',
1493
+ create_constraint=True,
1494
+ values_callable=lambda obj: [e.value for e in obj]),
1495
+ default=SubscriptionState.ACTIVE)
1496
+ last_processed: Mapped[Optional[datetime]] = mapped_column(DateTime, default=datetime.utcnow())
1497
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1498
+ lifetime: Mapped[Optional[datetime]] = mapped_column(DateTime)
1499
+ comments: Mapped[Optional[str]] = mapped_column(String(4000))
1500
+ retroactive: Mapped[bool] = mapped_column(Boolean(name='SUBSCRIPTIONS_RETROACTIVE_CHK', create_constraint=True),
1501
+ default=False)
1502
+ expired_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1503
+ _table_args = (PrimaryKeyConstraint('id', name='SUBSCRIPTIONS_PK'),
1504
+ UniqueConstraint('name', 'account', name='SUBSCRIPTIONS_NAME_ACCOUNT_UQ'),
1505
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='SUBSCRIPTIONS_ACCOUNT_FK'),
1506
+ CheckConstraint('RETROACTIVE IS NOT NULL', name='SUBSCRIPTIONS_RETROACTIVE_NN'),
1507
+ CheckConstraint('ACCOUNT IS NOT NULL', name='SUBSCRIPTIONS_ACCOUNT_NN'),
1508
+ Index('SUBSCRIPTIONS_STATE_IDX', 'state')) # Under Oracle this is a FB index
1509
+
1510
+
1511
+ class SubscriptionHistory(BASE, ModelBase):
1512
+ """Represents a subscription history"""
1513
+ __tablename__ = 'subscriptions_history'
1514
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1515
+ name: Mapped[str] = mapped_column(String(64))
1516
+ filter: Mapped[Optional[str]] = mapped_column(String(4000))
1517
+ replication_rules: Mapped[Optional[str]] = mapped_column(String(4000))
1518
+ policyid: Mapped[int] = mapped_column(SmallInteger, server_default='0')
1519
+ state: Mapped[SubscriptionState] = mapped_column(Enum(SubscriptionState, name='SUBSCRIPTIONS_HIST_STATE_CHK',
1520
+ create_constraint=True,
1521
+ values_callable=lambda obj: [e.value for e in obj]),
1522
+ default=SubscriptionState.ACTIVE)
1523
+ last_processed: Mapped[Optional[datetime]] = mapped_column(DateTime, default=datetime.utcnow())
1524
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1525
+ lifetime: Mapped[Optional[datetime]] = mapped_column(DateTime)
1526
+ comments: Mapped[Optional[str]] = mapped_column(String(4000))
1527
+ retroactive: Mapped[bool] = mapped_column(Boolean(name='SUBS_HISTORY_RETROACTIVE_CHK', create_constraint=True),
1528
+ default=False)
1529
+ expired_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1530
+ _table_args = (PrimaryKeyConstraint('id', 'updated_at', name='SUBSCRIPTIONS_HISTORY_PK'),)
1531
+
1532
+
1533
+ class Token(BASE, ModelBase):
1534
+ """Represents the authentication tokens and their lifetime"""
1535
+ __tablename__ = 'tokens'
1536
+ token: Mapped[str] = mapped_column(String(3072)) # account-identity-appid-uuid -> max length: (+ 30 1 255 1 32 1 32)
1537
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1538
+ refresh_token: Mapped[Optional[str]] = mapped_column(String(3072), default=None)
1539
+ refresh: Mapped[bool] = mapped_column(Boolean(name='TOKENS_REFRESH_CHK', create_constraint=True),
1540
+ default=False)
1541
+ refresh_start: Mapped[Optional[datetime]] = mapped_column(DateTime, default=None)
1542
+ refresh_expired_at: Mapped[Optional[datetime]] = mapped_column(DateTime, default=None)
1543
+ refresh_lifetime: Mapped[Optional[int]] = mapped_column(Integer())
1544
+ oidc_scope: Mapped[Optional[str]] = mapped_column(String(2048), default=None) # scopes define the specific actions applications can be allowed to do on a user's behalf
1545
+ identity: Mapped[Optional[str]] = mapped_column(String(2048))
1546
+ audience: Mapped[Optional[str]] = mapped_column(String(315), default=None)
1547
+ expired_at: Mapped[datetime] = mapped_column(DateTime, default=lambda: datetime.utcnow() + timedelta(seconds=3600)) # one hour lifetime by default
1548
+ ip: Mapped[Optional[str]] = mapped_column(String(39), nullable=True)
1549
+ _table_args = (PrimaryKeyConstraint('token', name='TOKENS_TOKEN_PK'), # not supported for primary key constraint mysql_length=255
1550
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='TOKENS_ACCOUNT_FK'),
1551
+ CheckConstraint('EXPIRED_AT IS NOT NULL', name='TOKENS_EXPIRED_AT_NN'),
1552
+ Index('TOKENS_ACCOUNT_EXPIRED_AT_IDX', 'account', 'expired_at'))
1553
+
1554
+
1555
+ class OAuthRequest(BASE, ModelBase):
1556
+ """Represents the authentication session parameters of OAuth 2.0 requests"""
1557
+ __tablename__ = 'oauth_requests'
1558
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1559
+ state: Mapped[str] = mapped_column(String(50))
1560
+ nonce: Mapped[Optional[str]] = mapped_column(String(50))
1561
+ access_msg: Mapped[Optional[str]] = mapped_column(String(2048))
1562
+ redirect_msg: Mapped[Optional[str]] = mapped_column(String(4000))
1563
+ refresh_lifetime: Mapped[Optional[int]] = mapped_column(Integer())
1564
+ ip: Mapped[Optional[str]] = mapped_column(String(39), nullable=True)
1565
+ expired_at: Mapped[datetime] = mapped_column(DateTime, default=lambda: datetime.utcnow() + timedelta(seconds=600)) # 10 min lifetime by default
1566
+ _table_args = (PrimaryKeyConstraint('state', name='OAUTH_REQUESTS_STATE_PK'),
1567
+ CheckConstraint('EXPIRED_AT IS NOT NULL', name='OAUTH_REQUESTS_EXPIRED_AT_NN'),
1568
+ Index('OAUTH_REQUESTS_ACC_EXP_AT_IDX', 'account', 'expired_at'),
1569
+ Index('OAUTH_REQUESTS_ACCESS_MSG_IDX', 'access_msg'))
1570
+
1571
+
1572
+ class Message(BASE, ModelBase):
1573
+ """Represents the event messages"""
1574
+ __tablename__ = 'messages'
1575
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1576
+ event_type: Mapped[str] = mapped_column(String(256))
1577
+ payload: Mapped[str] = mapped_column(String(4000))
1578
+ payload_nolimit: Mapped[Optional[str]] = mapped_column(Text)
1579
+ services: Mapped[Optional[str]] = mapped_column(String(256))
1580
+ _table_args = (PrimaryKeyConstraint('id', name='MESSAGES_ID_PK'),
1581
+ CheckConstraint('EVENT_TYPE IS NOT NULL', name='MESSAGES_EVENT_TYPE_NN'),
1582
+ CheckConstraint('PAYLOAD IS NOT NULL', name='MESSAGES_PAYLOAD_NN'),
1583
+ Index('MESSAGES_SERVICES_IDX', 'services', 'event_type'))
1584
+
1585
+
1586
+ class MessageHistory(BASE, ModelBase):
1587
+ """Represents the history of event messages"""
1588
+ __tablename__ = 'messages_history'
1589
+ id: Mapped[str] = mapped_column(GUID())
1590
+ event_type: Mapped[Optional[str]] = mapped_column(String(1024))
1591
+ payload: Mapped[Optional[str]] = mapped_column(String(4000))
1592
+ payload_nolimit: Mapped[Optional[str]] = mapped_column(Text)
1593
+ services: Mapped[Optional[str]] = mapped_column(String(2048))
1594
+ __mapper_args__ = {
1595
+ 'primary_key': [id] # Fake primary key for SQLA
1596
+ }
1597
+ _table_args = () # PrimaryKeyConstraint('id', name='MESSAGES_HIST_ID_PK'),) # PK needed for SQLA only
1598
+
1599
+
1600
+ class AlembicVersion(BASE):
1601
+ """Table used to pinpoint actual database schema release."""
1602
+ __tablename__ = "alembic_version"
1603
+ version_num: Mapped[str] = mapped_column(String(32), primary_key=True, nullable=False)
1604
+
1605
+
1606
+ class Config(BASE, ModelBase):
1607
+ """Represents the configuration"""
1608
+ __tablename__ = 'configs'
1609
+ section: Mapped[str] = mapped_column(String(128))
1610
+ opt: Mapped[str] = mapped_column(String(128))
1611
+ value: Mapped[Optional[str]] = mapped_column(String(4000))
1612
+ _table_args = (PrimaryKeyConstraint('section', 'opt', name='CONFIGS_PK'), )
1613
+
1614
+
1615
+ class ConfigHistory(BASE, ModelBase):
1616
+ """Represents the configuration"""
1617
+ __tablename__ = 'configs_history'
1618
+ section: Mapped[str] = mapped_column(String(128))
1619
+ opt: Mapped[str] = mapped_column(String(128))
1620
+ value: Mapped[Optional[str]] = mapped_column(String(4000))
1621
+ __mapper_args__ = {
1622
+ 'primary_key': [section, opt] # Fake primary key for SQLA
1623
+ }
1624
+ _table_args = ()
1625
+
1626
+
1627
+ class Heartbeat(BASE, ModelBase):
1628
+ """Represents the status and heartbeat of the running daemons and services"""
1629
+ __tablename__ = 'heartbeats'
1630
+ executable: Mapped[str] = mapped_column(String(64)) # SHA-2
1631
+ readable: Mapped[Optional[str]] = mapped_column(String(4000))
1632
+ hostname: Mapped[str] = mapped_column(String(128))
1633
+ pid: Mapped[int] = mapped_column(Integer, autoincrement=False)
1634
+ thread_id: Mapped[int] = mapped_column(BigInteger, autoincrement=False)
1635
+ thread_name: Mapped[Optional[str]] = mapped_column(String(64))
1636
+ payload: Mapped[Optional[str]] = mapped_column(String(3000))
1637
+ _table_args = (PrimaryKeyConstraint('executable', 'hostname', 'pid', 'thread_id', name='HEARTBEATS_PK'), )
1638
+
1639
+
1640
+ class NamingConvention(BASE, ModelBase):
1641
+ """Represents naming conventions for name within a scope"""
1642
+ __tablename__ = 'naming_conventions'
1643
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1644
+ regexp: Mapped[Optional[str]] = mapped_column(String(255))
1645
+ convention_type: Mapped[KeyType] = mapped_column(Enum(KeyType, name='CVT_TYPE_CHK',
1646
+ create_constraint=True,
1647
+ values_callable=lambda obj: [e.value for e in obj]))
1648
+ _table_args = (PrimaryKeyConstraint('scope', name='NAMING_CONVENTIONS_PK'),
1649
+ ForeignKeyConstraint(['scope'], ['scopes.scope'], name='NAMING_CONVENTIONS_SCOPE_FK'))
1650
+
1651
+
1652
+ class LifetimeException(BASE, ModelBase):
1653
+ """Represents the exceptions to the lifetime model"""
1654
+ __tablename__ = 'lifetime_except'
1655
+ id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
1656
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1657
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1658
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='LIFETIME_EXCEPT_TYPE_CHK',
1659
+ create_constraint=True,
1660
+ values_callable=lambda obj: [e.value for e in obj]))
1661
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1662
+ pattern: Mapped[Optional[str]] = mapped_column(String(255))
1663
+ comments: Mapped[Optional[str]] = mapped_column(String(4000))
1664
+ state: Mapped[LifetimeExceptionsState] = mapped_column(Enum(LifetimeExceptionsState, name='LIFETIME_EXCEPT_STATE_CHK',
1665
+ create_constraint=True,
1666
+ values_callable=lambda obj: [e.value for e in obj]))
1667
+ expires_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
1668
+ _table_args = (PrimaryKeyConstraint('id', 'scope', 'name', 'did_type', 'account', name='LIFETIME_EXCEPT_PK'),
1669
+ CheckConstraint('SCOPE IS NOT NULL', name='LIFETIME_EXCEPT_SCOPE_NN'),
1670
+ CheckConstraint('NAME IS NOT NULL', name='LIFETIME_EXCEPT_NAME_NN'),
1671
+ CheckConstraint('DID_TYPE IS NOT NULL', name='LIFETIME_EXCEPT_DID_TYPE_NN'),
1672
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='LIFETIME_EXCEPT_ACCOUNT_FK'))
1673
+
1674
+
1675
+ class VO(BASE, ModelBase):
1676
+ """Represents the VOS in a MultiVO setup"""
1677
+ __tablename__ = 'vos'
1678
+ vo: Mapped[str] = mapped_column(String(3))
1679
+ description: Mapped[Optional[str]] = mapped_column(String(255))
1680
+ email: Mapped[Optional[str]] = mapped_column(String(255))
1681
+ _table_args = (PrimaryKeyConstraint('vo', name='VOS_PK'), )
1682
+
1683
+
1684
+ class DidFollowed(BASE, ModelBase):
1685
+ """Represents the datasets followed by a user"""
1686
+ __tablename__ = 'dids_followed'
1687
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1688
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1689
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1690
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='DIDS_FOLLOWED_TYPE_CHK',
1691
+ create_constraint=True,
1692
+ values_callable=lambda obj: [e.value for e in obj]))
1693
+ _table_args = (PrimaryKeyConstraint('scope', 'name', 'account', name='DIDS_FOLLOWED_PK'),
1694
+ CheckConstraint('SCOPE IS NOT NULL', name='DIDS_FOLLOWED_SCOPE_NN'),
1695
+ CheckConstraint('NAME IS NOT NULL', name='DIDS_FOLLOWED_NAME_NN'),
1696
+ CheckConstraint('ACCOUNT IS NOT NULL', name='DIDS_FOLLOWED_ACCOUNT_NN'),
1697
+ CheckConstraint('DID_TYPE IS NOT NULL', name='DIDS_FOLLOWED_DID_TYPE_NN'),
1698
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='DIDS_FOLLOWED_ACCOUNT_FK'),
1699
+ ForeignKeyConstraint(['scope', 'name'], ['dids.scope', 'dids.name'], name='DIDS_FOLLOWED_SCOPE_NAME_FK'))
1700
+
1701
+
1702
+ class FollowEvent(BASE, ModelBase):
1703
+ """Represents the events affecting the datasets which are followed"""
1704
+ __tablename__ = 'dids_followed_events'
1705
+ scope: Mapped[InternalScope] = mapped_column(InternalScopeString(common_schema.get_schema_value('SCOPE_LENGTH')))
1706
+ name: Mapped[str] = mapped_column(String(common_schema.get_schema_value('NAME_LENGTH')))
1707
+ account: Mapped[InternalAccount] = mapped_column(InternalAccountString(common_schema.get_schema_value('ACCOUNT_LENGTH')))
1708
+ did_type: Mapped[DIDType] = mapped_column(Enum(DIDType, name='DIDS_FOLLOWED_EVENTS_TYPE_CHK',
1709
+ create_constraint=True,
1710
+ values_callable=lambda obj: [e.value for e in obj]))
1711
+ event_type: Mapped[Optional[str]] = mapped_column(String(1024))
1712
+ payload: Mapped[Optional[str]] = mapped_column(Text)
1713
+ _table_args = (PrimaryKeyConstraint('scope', 'name', 'account', name='DIDS_FOLLOWED_EVENTS_PK'),
1714
+ CheckConstraint('SCOPE IS NOT NULL', name='DIDS_FOLLOWED_EVENTS_SCOPE_NN'),
1715
+ CheckConstraint('NAME IS NOT NULL', name='DIDS_FOLLOWED_EVENTS_NAME_NN'),
1716
+ CheckConstraint('ACCOUNT IS NOT NULL', name='DIDS_FOLLOWED_EVENTS_ACC_NN'),
1717
+ CheckConstraint('DID_TYPE IS NOT NULL', name='DIDS_FOLLOWED_EVENTS_TYPE_NN'),
1718
+ ForeignKeyConstraint(['account'], ['accounts.account'], name='DIDS_FOLLOWED_EVENTS_ACC_FK'),
1719
+ Index('DIDS_FOLLOWED_EVENTS_ACC_IDX', 'account'))
1720
+
1721
+
1722
+ def register_models(engine: Engine) -> None:
1723
+ """
1724
+ Creates database tables for all models in the `BASE.metadata` schema with the given engine.
1725
+ Functionally this creates all models, as they all inherit from BASE and exist in the same `BASE.metadata` schema.
1726
+
1727
+ :param engine: engine to register the models with
1728
+ :type engine: sqlalchemy.engine.Engine
1729
+ :returns: None
1730
+ """
1731
+ BASE.metadata.create_all(engine)
1732
+
1733
+
1734
+ def unregister_models(engine: Engine) -> None:
1735
+ """
1736
+ Drops database tables for all models in the `BASE.metadata` schema with the given engine.
1737
+ Functionally this drops all models, as they all inherit from BASE and exist in the same `BASE.metadata` schema.
1738
+
1739
+ :param engine: The engine to unregister the models with
1740
+ :type engine: sqlalchemy.engine.Engine
1741
+ :returns: None
1742
+ """
1743
+ BASE.metadata.drop_all(engine)