rucio 35.7.0__py3-none-any.whl

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

Potentially problematic release.


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

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