rucio 37.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/__init__.py +17 -0
- rucio/alembicrevision.py +15 -0
- rucio/cli/__init__.py +14 -0
- rucio/cli/account.py +216 -0
- rucio/cli/bin_legacy/__init__.py +13 -0
- rucio/cli/bin_legacy/rucio.py +2825 -0
- rucio/cli/bin_legacy/rucio_admin.py +2500 -0
- rucio/cli/command.py +272 -0
- rucio/cli/config.py +72 -0
- rucio/cli/did.py +191 -0
- rucio/cli/download.py +128 -0
- rucio/cli/lifetime_exception.py +33 -0
- rucio/cli/replica.py +162 -0
- rucio/cli/rse.py +293 -0
- rucio/cli/rule.py +158 -0
- rucio/cli/scope.py +40 -0
- rucio/cli/subscription.py +73 -0
- rucio/cli/upload.py +60 -0
- rucio/cli/utils.py +226 -0
- rucio/client/__init__.py +15 -0
- rucio/client/accountclient.py +432 -0
- rucio/client/accountlimitclient.py +183 -0
- rucio/client/baseclient.py +983 -0
- rucio/client/client.py +120 -0
- rucio/client/configclient.py +126 -0
- rucio/client/credentialclient.py +59 -0
- rucio/client/didclient.py +868 -0
- rucio/client/diracclient.py +56 -0
- rucio/client/downloadclient.py +1783 -0
- rucio/client/exportclient.py +44 -0
- rucio/client/fileclient.py +50 -0
- rucio/client/importclient.py +42 -0
- rucio/client/lifetimeclient.py +90 -0
- rucio/client/lockclient.py +109 -0
- rucio/client/metaconventionsclient.py +140 -0
- rucio/client/pingclient.py +44 -0
- rucio/client/replicaclient.py +452 -0
- rucio/client/requestclient.py +125 -0
- rucio/client/richclient.py +317 -0
- rucio/client/rseclient.py +746 -0
- rucio/client/ruleclient.py +294 -0
- rucio/client/scopeclient.py +90 -0
- rucio/client/subscriptionclient.py +173 -0
- rucio/client/touchclient.py +82 -0
- rucio/client/uploadclient.py +969 -0
- rucio/common/__init__.py +13 -0
- rucio/common/bittorrent.py +234 -0
- rucio/common/cache.py +111 -0
- rucio/common/checksum.py +168 -0
- rucio/common/client.py +122 -0
- rucio/common/config.py +788 -0
- rucio/common/constants.py +217 -0
- rucio/common/constraints.py +17 -0
- rucio/common/didtype.py +237 -0
- rucio/common/dumper/__init__.py +342 -0
- rucio/common/dumper/consistency.py +497 -0
- rucio/common/dumper/data_models.py +362 -0
- rucio/common/dumper/path_parsing.py +75 -0
- rucio/common/exception.py +1208 -0
- rucio/common/extra.py +31 -0
- rucio/common/logging.py +420 -0
- rucio/common/pcache.py +1409 -0
- rucio/common/plugins.py +185 -0
- rucio/common/policy.py +93 -0
- rucio/common/schema/__init__.py +200 -0
- rucio/common/schema/generic.py +416 -0
- rucio/common/schema/generic_multi_vo.py +395 -0
- rucio/common/stomp_utils.py +423 -0
- rucio/common/stopwatch.py +55 -0
- rucio/common/test_rucio_server.py +154 -0
- rucio/common/types.py +483 -0
- rucio/common/utils.py +1688 -0
- rucio/core/__init__.py +13 -0
- rucio/core/account.py +496 -0
- rucio/core/account_counter.py +236 -0
- rucio/core/account_limit.py +425 -0
- rucio/core/authentication.py +620 -0
- rucio/core/config.py +437 -0
- rucio/core/credential.py +224 -0
- rucio/core/did.py +3004 -0
- rucio/core/did_meta_plugins/__init__.py +252 -0
- rucio/core/did_meta_plugins/did_column_meta.py +331 -0
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +165 -0
- rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
- rucio/core/did_meta_plugins/filter_engine.py +672 -0
- rucio/core/did_meta_plugins/json_meta.py +240 -0
- rucio/core/did_meta_plugins/mongo_meta.py +229 -0
- rucio/core/did_meta_plugins/postgres_meta.py +352 -0
- rucio/core/dirac.py +237 -0
- rucio/core/distance.py +187 -0
- rucio/core/exporter.py +59 -0
- rucio/core/heartbeat.py +363 -0
- rucio/core/identity.py +301 -0
- rucio/core/importer.py +260 -0
- rucio/core/lifetime_exception.py +377 -0
- rucio/core/lock.py +577 -0
- rucio/core/message.py +288 -0
- rucio/core/meta_conventions.py +203 -0
- rucio/core/monitor.py +448 -0
- rucio/core/naming_convention.py +195 -0
- rucio/core/nongrid_trace.py +136 -0
- rucio/core/oidc.py +1463 -0
- rucio/core/permission/__init__.py +161 -0
- rucio/core/permission/generic.py +1124 -0
- rucio/core/permission/generic_multi_vo.py +1144 -0
- rucio/core/quarantined_replica.py +224 -0
- rucio/core/replica.py +4483 -0
- rucio/core/replica_sorter.py +362 -0
- rucio/core/request.py +3091 -0
- rucio/core/rse.py +2079 -0
- rucio/core/rse_counter.py +185 -0
- rucio/core/rse_expression_parser.py +459 -0
- rucio/core/rse_selector.py +304 -0
- rucio/core/rule.py +4484 -0
- rucio/core/rule_grouping.py +1620 -0
- rucio/core/scope.py +181 -0
- rucio/core/subscription.py +362 -0
- rucio/core/topology.py +490 -0
- rucio/core/trace.py +375 -0
- rucio/core/transfer.py +1531 -0
- rucio/core/vo.py +169 -0
- rucio/core/volatile_replica.py +151 -0
- rucio/daemons/__init__.py +13 -0
- rucio/daemons/abacus/__init__.py +13 -0
- rucio/daemons/abacus/account.py +116 -0
- rucio/daemons/abacus/collection_replica.py +124 -0
- rucio/daemons/abacus/rse.py +117 -0
- rucio/daemons/atropos/__init__.py +13 -0
- rucio/daemons/atropos/atropos.py +242 -0
- rucio/daemons/auditor/__init__.py +289 -0
- rucio/daemons/auditor/hdfs.py +97 -0
- rucio/daemons/auditor/srmdumps.py +355 -0
- rucio/daemons/automatix/__init__.py +13 -0
- rucio/daemons/automatix/automatix.py +304 -0
- rucio/daemons/badreplicas/__init__.py +13 -0
- rucio/daemons/badreplicas/minos.py +322 -0
- rucio/daemons/badreplicas/minos_temporary_expiration.py +171 -0
- rucio/daemons/badreplicas/necromancer.py +196 -0
- rucio/daemons/bb8/__init__.py +13 -0
- rucio/daemons/bb8/bb8.py +353 -0
- rucio/daemons/bb8/common.py +759 -0
- rucio/daemons/bb8/nuclei_background_rebalance.py +153 -0
- rucio/daemons/bb8/t2_background_rebalance.py +153 -0
- rucio/daemons/cache/__init__.py +13 -0
- rucio/daemons/cache/consumer.py +133 -0
- rucio/daemons/common.py +405 -0
- rucio/daemons/conveyor/__init__.py +13 -0
- rucio/daemons/conveyor/common.py +562 -0
- rucio/daemons/conveyor/finisher.py +529 -0
- rucio/daemons/conveyor/poller.py +394 -0
- rucio/daemons/conveyor/preparer.py +205 -0
- rucio/daemons/conveyor/receiver.py +179 -0
- rucio/daemons/conveyor/stager.py +133 -0
- rucio/daemons/conveyor/submitter.py +403 -0
- rucio/daemons/conveyor/throttler.py +532 -0
- rucio/daemons/follower/__init__.py +13 -0
- rucio/daemons/follower/follower.py +101 -0
- rucio/daemons/hermes/__init__.py +13 -0
- rucio/daemons/hermes/hermes.py +534 -0
- rucio/daemons/judge/__init__.py +13 -0
- rucio/daemons/judge/cleaner.py +159 -0
- rucio/daemons/judge/evaluator.py +185 -0
- rucio/daemons/judge/injector.py +162 -0
- rucio/daemons/judge/repairer.py +154 -0
- rucio/daemons/oauthmanager/__init__.py +13 -0
- rucio/daemons/oauthmanager/oauthmanager.py +198 -0
- rucio/daemons/reaper/__init__.py +13 -0
- rucio/daemons/reaper/dark_reaper.py +282 -0
- rucio/daemons/reaper/reaper.py +739 -0
- rucio/daemons/replicarecoverer/__init__.py +13 -0
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +626 -0
- rucio/daemons/rsedecommissioner/__init__.py +13 -0
- rucio/daemons/rsedecommissioner/config.py +81 -0
- rucio/daemons/rsedecommissioner/profiles/__init__.py +24 -0
- rucio/daemons/rsedecommissioner/profiles/atlas.py +60 -0
- rucio/daemons/rsedecommissioner/profiles/generic.py +452 -0
- rucio/daemons/rsedecommissioner/profiles/types.py +93 -0
- rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
- rucio/daemons/storage/__init__.py +13 -0
- rucio/daemons/storage/consistency/__init__.py +13 -0
- rucio/daemons/storage/consistency/actions.py +848 -0
- rucio/daemons/tracer/__init__.py +13 -0
- rucio/daemons/tracer/kronos.py +511 -0
- rucio/daemons/transmogrifier/__init__.py +13 -0
- rucio/daemons/transmogrifier/transmogrifier.py +762 -0
- rucio/daemons/undertaker/__init__.py +13 -0
- rucio/daemons/undertaker/undertaker.py +137 -0
- rucio/db/__init__.py +13 -0
- rucio/db/sqla/__init__.py +52 -0
- rucio/db/sqla/constants.py +206 -0
- rucio/db/sqla/migrate_repo/__init__.py +13 -0
- rucio/db/sqla/migrate_repo/env.py +110 -0
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +70 -0
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +91 -0
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +76 -0
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +43 -0
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +50 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +68 -0
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +40 -0
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +45 -0
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +60 -0
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +40 -0
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +140 -0
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +73 -0
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +74 -0
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +43 -0
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +50 -0
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +134 -0
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +64 -0
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +39 -0
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +64 -0
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +51 -0
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +41 -0
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +43 -0
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +44 -0
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +53 -0
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +38 -0
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +47 -0
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +57 -0
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +69 -0
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +42 -0
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +46 -0
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +40 -0
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +67 -0
- rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +44 -0
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +77 -0
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +60 -0
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +72 -0
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +42 -0
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +65 -0
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +133 -0
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +76 -0
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +60 -0
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +44 -0
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +64 -0
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +40 -0
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +43 -0
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +44 -0
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +78 -0
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +41 -0
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +44 -0
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +49 -0
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +40 -0
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +63 -0
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +55 -0
- rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +45 -0
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +47 -0
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +58 -0
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +45 -0
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +106 -0
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +55 -0
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +50 -0
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +43 -0
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +41 -0
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +91 -0
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +72 -0
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +49 -0
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +43 -0
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +53 -0
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +45 -0
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +68 -0
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +45 -0
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +94 -0
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +54 -0
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +72 -0
- rucio/db/sqla/migrate_repo/versions/a08fa8de1545_transfer_stats_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +76 -0
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +47 -0
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +121 -0
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +59 -0
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +52 -0
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +54 -0
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +64 -0
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +49 -0
- rucio/db/sqla/migrate_repo/versions/b0070f3695c8_add_deletedidmeta_table.py +57 -0
- rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +43 -0
- rucio/db/sqla/migrate_repo/versions/b5493606bbf5_fix_primary_key_for_subscription_history.py +41 -0
- rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +91 -0
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +40 -0
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +143 -0
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +76 -0
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +50 -0
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +72 -0
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +43 -0
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +65 -0
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +47 -0
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +146 -0
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +104 -0
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +44 -0
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +43 -0
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +103 -0
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +49 -0
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +104 -0
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +29 -0
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +74 -0
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +43 -0
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +37 -0
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +43 -0
- rucio/db/sqla/models.py +1743 -0
- rucio/db/sqla/sautils.py +55 -0
- rucio/db/sqla/session.py +529 -0
- rucio/db/sqla/types.py +206 -0
- rucio/db/sqla/util.py +543 -0
- rucio/gateway/__init__.py +13 -0
- rucio/gateway/account.py +345 -0
- rucio/gateway/account_limit.py +363 -0
- rucio/gateway/authentication.py +381 -0
- rucio/gateway/config.py +227 -0
- rucio/gateway/credential.py +70 -0
- rucio/gateway/did.py +987 -0
- rucio/gateway/dirac.py +83 -0
- rucio/gateway/exporter.py +60 -0
- rucio/gateway/heartbeat.py +76 -0
- rucio/gateway/identity.py +189 -0
- rucio/gateway/importer.py +46 -0
- rucio/gateway/lifetime_exception.py +121 -0
- rucio/gateway/lock.py +153 -0
- rucio/gateway/meta_conventions.py +98 -0
- rucio/gateway/permission.py +74 -0
- rucio/gateway/quarantined_replica.py +79 -0
- rucio/gateway/replica.py +538 -0
- rucio/gateway/request.py +330 -0
- rucio/gateway/rse.py +632 -0
- rucio/gateway/rule.py +437 -0
- rucio/gateway/scope.py +100 -0
- rucio/gateway/subscription.py +280 -0
- rucio/gateway/vo.py +126 -0
- rucio/rse/__init__.py +96 -0
- rucio/rse/protocols/__init__.py +13 -0
- rucio/rse/protocols/bittorrent.py +194 -0
- rucio/rse/protocols/cache.py +111 -0
- rucio/rse/protocols/dummy.py +100 -0
- rucio/rse/protocols/gfal.py +708 -0
- rucio/rse/protocols/globus.py +243 -0
- rucio/rse/protocols/http_cache.py +82 -0
- rucio/rse/protocols/mock.py +123 -0
- rucio/rse/protocols/ngarc.py +209 -0
- rucio/rse/protocols/posix.py +250 -0
- rucio/rse/protocols/protocol.py +361 -0
- rucio/rse/protocols/rclone.py +365 -0
- rucio/rse/protocols/rfio.py +145 -0
- rucio/rse/protocols/srm.py +338 -0
- rucio/rse/protocols/ssh.py +414 -0
- rucio/rse/protocols/storm.py +195 -0
- rucio/rse/protocols/webdav.py +594 -0
- rucio/rse/protocols/xrootd.py +302 -0
- rucio/rse/rsemanager.py +881 -0
- rucio/rse/translation.py +260 -0
- rucio/tests/__init__.py +13 -0
- rucio/tests/common.py +280 -0
- rucio/tests/common_server.py +149 -0
- rucio/transfertool/__init__.py +13 -0
- rucio/transfertool/bittorrent.py +200 -0
- rucio/transfertool/bittorrent_driver.py +50 -0
- rucio/transfertool/bittorrent_driver_qbittorrent.py +134 -0
- rucio/transfertool/fts3.py +1600 -0
- rucio/transfertool/fts3_plugins.py +152 -0
- rucio/transfertool/globus.py +201 -0
- rucio/transfertool/globus_library.py +181 -0
- rucio/transfertool/mock.py +89 -0
- rucio/transfertool/transfertool.py +221 -0
- rucio/vcsversion.py +11 -0
- rucio/version.py +45 -0
- rucio/web/__init__.py +13 -0
- rucio/web/rest/__init__.py +13 -0
- rucio/web/rest/flaskapi/__init__.py +13 -0
- rucio/web/rest/flaskapi/authenticated_bp.py +27 -0
- rucio/web/rest/flaskapi/v1/__init__.py +13 -0
- rucio/web/rest/flaskapi/v1/accountlimits.py +236 -0
- rucio/web/rest/flaskapi/v1/accounts.py +1103 -0
- rucio/web/rest/flaskapi/v1/archives.py +102 -0
- rucio/web/rest/flaskapi/v1/auth.py +1644 -0
- rucio/web/rest/flaskapi/v1/common.py +426 -0
- rucio/web/rest/flaskapi/v1/config.py +304 -0
- rucio/web/rest/flaskapi/v1/credentials.py +213 -0
- rucio/web/rest/flaskapi/v1/dids.py +2340 -0
- rucio/web/rest/flaskapi/v1/dirac.py +116 -0
- rucio/web/rest/flaskapi/v1/export.py +75 -0
- rucio/web/rest/flaskapi/v1/heartbeats.py +127 -0
- rucio/web/rest/flaskapi/v1/identities.py +285 -0
- rucio/web/rest/flaskapi/v1/import.py +132 -0
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +312 -0
- rucio/web/rest/flaskapi/v1/locks.py +358 -0
- rucio/web/rest/flaskapi/v1/main.py +91 -0
- rucio/web/rest/flaskapi/v1/meta_conventions.py +241 -0
- rucio/web/rest/flaskapi/v1/metrics.py +36 -0
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
- rucio/web/rest/flaskapi/v1/ping.py +88 -0
- rucio/web/rest/flaskapi/v1/redirect.py +366 -0
- rucio/web/rest/flaskapi/v1/replicas.py +1894 -0
- rucio/web/rest/flaskapi/v1/requests.py +998 -0
- rucio/web/rest/flaskapi/v1/rses.py +2250 -0
- rucio/web/rest/flaskapi/v1/rules.py +854 -0
- rucio/web/rest/flaskapi/v1/scopes.py +159 -0
- rucio/web/rest/flaskapi/v1/subscriptions.py +650 -0
- rucio/web/rest/flaskapi/v1/templates/auth_crash.html +80 -0
- rucio/web/rest/flaskapi/v1/templates/auth_granted.html +82 -0
- rucio/web/rest/flaskapi/v1/traces.py +137 -0
- rucio/web/rest/flaskapi/v1/types.py +20 -0
- rucio/web/rest/flaskapi/v1/vos.py +278 -0
- rucio/web/rest/main.py +18 -0
- rucio/web/rest/metrics.py +27 -0
- rucio/web/rest/ping.py +27 -0
- rucio-37.0.0rc1.data/data/rucio/etc/alembic.ini.template +71 -0
- rucio-37.0.0rc1.data/data/rucio/etc/alembic_offline.ini.template +74 -0
- rucio-37.0.0rc1.data/data/rucio/etc/globus-config.yml.template +5 -0
- rucio-37.0.0rc1.data/data/rucio/etc/ldap.cfg.template +30 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.atlas.client.template +43 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.template +241 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio_multi_vo.cfg.template +217 -0
- rucio-37.0.0rc1.data/data/rucio/requirements.server.txt +297 -0
- rucio-37.0.0rc1.data/data/rucio/tools/bootstrap.py +34 -0
- rucio-37.0.0rc1.data/data/rucio/tools/merge_rucio_configs.py +144 -0
- rucio-37.0.0rc1.data/data/rucio/tools/reset_database.py +40 -0
- rucio-37.0.0rc1.data/scripts/rucio +133 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-account +74 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-collection-replica +46 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-rse +78 -0
- rucio-37.0.0rc1.data/scripts/rucio-admin +97 -0
- rucio-37.0.0rc1.data/scripts/rucio-atropos +60 -0
- rucio-37.0.0rc1.data/scripts/rucio-auditor +206 -0
- rucio-37.0.0rc1.data/scripts/rucio-automatix +50 -0
- rucio-37.0.0rc1.data/scripts/rucio-bb8 +57 -0
- rucio-37.0.0rc1.data/scripts/rucio-cache-client +141 -0
- rucio-37.0.0rc1.data/scripts/rucio-cache-consumer +42 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-finisher +58 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-poller +66 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-preparer +37 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-receiver +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-stager +76 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-submitter +139 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-throttler +104 -0
- rucio-37.0.0rc1.data/scripts/rucio-dark-reaper +53 -0
- rucio-37.0.0rc1.data/scripts/rucio-dumper +160 -0
- rucio-37.0.0rc1.data/scripts/rucio-follower +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-hermes +54 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-cleaner +89 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-evaluator +137 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-injector +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-repairer +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-kronos +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-minos +53 -0
- rucio-37.0.0rc1.data/scripts/rucio-minos-temporary-expiration +50 -0
- rucio-37.0.0rc1.data/scripts/rucio-necromancer +120 -0
- rucio-37.0.0rc1.data/scripts/rucio-oauth-manager +63 -0
- rucio-37.0.0rc1.data/scripts/rucio-reaper +83 -0
- rucio-37.0.0rc1.data/scripts/rucio-replica-recoverer +248 -0
- rucio-37.0.0rc1.data/scripts/rucio-rse-decommissioner +66 -0
- rucio-37.0.0rc1.data/scripts/rucio-storage-consistency-actions +74 -0
- rucio-37.0.0rc1.data/scripts/rucio-transmogrifier +77 -0
- rucio-37.0.0rc1.data/scripts/rucio-undertaker +76 -0
- rucio-37.0.0rc1.dist-info/METADATA +92 -0
- rucio-37.0.0rc1.dist-info/RECORD +487 -0
- rucio-37.0.0rc1.dist-info/WHEEL +5 -0
- rucio-37.0.0rc1.dist-info/licenses/AUTHORS.rst +100 -0
- rucio-37.0.0rc1.dist-info/licenses/LICENSE +201 -0
- rucio-37.0.0rc1.dist-info/top_level.txt +1 -0
rucio/core/scope.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from re import match
|
|
16
|
+
from traceback import format_exc
|
|
17
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
18
|
+
|
|
19
|
+
from sqlalchemy import and_, select
|
|
20
|
+
from sqlalchemy.exc import IntegrityError
|
|
21
|
+
|
|
22
|
+
from rucio.common.exception import AccountNotFound, Duplicate, RucioException, VONotFound
|
|
23
|
+
from rucio.core.vo import vo_exists
|
|
24
|
+
from rucio.db.sqla import models
|
|
25
|
+
from rucio.db.sqla.constants import AccountStatus, ScopeStatus
|
|
26
|
+
from rucio.db.sqla.session import read_session, transactional_session
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from sqlalchemy.orm import Session
|
|
30
|
+
|
|
31
|
+
from rucio.common.types import InternalScope
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@transactional_session
|
|
35
|
+
def add_scope(scope, account, *, session: "Session"):
|
|
36
|
+
""" add a scope for the given account name.
|
|
37
|
+
|
|
38
|
+
:param scope: the name for the new scope.
|
|
39
|
+
:param account: the account to add the scope to.
|
|
40
|
+
:param session: The database session in use.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
if not vo_exists(vo=scope.vo, session=session):
|
|
44
|
+
raise VONotFound('VO {} not found'.format(scope.vo))
|
|
45
|
+
|
|
46
|
+
stmt = select(
|
|
47
|
+
models.Account
|
|
48
|
+
).where(
|
|
49
|
+
and_(models.Account.account == account,
|
|
50
|
+
models.Account.status == AccountStatus.ACTIVE)
|
|
51
|
+
)
|
|
52
|
+
if session.execute(stmt).first() is None:
|
|
53
|
+
raise AccountNotFound('Account ID \'%s\' does not exist' % account)
|
|
54
|
+
|
|
55
|
+
new_scope = models.Scope(scope=scope, account=account, status=ScopeStatus.OPEN)
|
|
56
|
+
try:
|
|
57
|
+
new_scope.save(session=session)
|
|
58
|
+
except IntegrityError as e:
|
|
59
|
+
if match('.*IntegrityError.*ORA-00001: unique constraint.*SCOPES_PK.*violated.*', e.args[0]) \
|
|
60
|
+
or match('.*IntegrityError.*Duplicate entry.*for key.*', e.args[0]) \
|
|
61
|
+
or match('.*IntegrityError.*UNIQUE constraint failed: scopes.scope.*', e.args[0]) \
|
|
62
|
+
or match('.*IntegrityError.*duplicate key value violates unique constraint.*', e.args[0]) \
|
|
63
|
+
or match('.*UniqueViolation.*duplicate key value violates unique constraint.*', e.args[0]) \
|
|
64
|
+
or match('.*IntegrityError.*columns? .*not unique.*', e.args[0]):
|
|
65
|
+
raise Duplicate('Scope \'%s\' already exists!' % scope)
|
|
66
|
+
else:
|
|
67
|
+
raise RucioException(e)
|
|
68
|
+
except:
|
|
69
|
+
raise RucioException(str(format_exc()))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@read_session
|
|
73
|
+
def bulk_add_scopes(scopes, account, skip_existing=False, *, session: "Session"):
|
|
74
|
+
""" add a group of scopes, this call should not be exposed to users.
|
|
75
|
+
|
|
76
|
+
:param scopes: a list of scopes to be added.
|
|
77
|
+
:param account: the account associated to the scopes.
|
|
78
|
+
:param session: The database session in use.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
for scope in scopes:
|
|
82
|
+
try:
|
|
83
|
+
add_scope(scope, account, session=session)
|
|
84
|
+
except Duplicate:
|
|
85
|
+
if not skip_existing:
|
|
86
|
+
raise
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@read_session
|
|
90
|
+
def list_scopes(filter_: Optional[dict[str, Any]] = None, *, session: "Session") -> list["InternalScope"]:
|
|
91
|
+
"""
|
|
92
|
+
Lists all scopes.
|
|
93
|
+
:param filter_: Dictionary of attributes by which the input data should be filtered
|
|
94
|
+
:param session: The database session in use.
|
|
95
|
+
|
|
96
|
+
:returns: A list containing all scopes.
|
|
97
|
+
"""
|
|
98
|
+
filter_ = filter_ or {}
|
|
99
|
+
stmt = select(
|
|
100
|
+
models.Scope.scope
|
|
101
|
+
).where(
|
|
102
|
+
models.Scope.status != ScopeStatus.DELETED
|
|
103
|
+
)
|
|
104
|
+
for filter_type in filter_:
|
|
105
|
+
if filter_type == 'scope':
|
|
106
|
+
if '*' in filter_['scope'].internal:
|
|
107
|
+
scope_str = filter_['scope'].internal.replace('*', '%')
|
|
108
|
+
stmt = stmt.where(
|
|
109
|
+
models.Scope.scope.like(scope_str)
|
|
110
|
+
)
|
|
111
|
+
else:
|
|
112
|
+
stmt = stmt.where(
|
|
113
|
+
models.Scope.scope == filter_['scope']
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
return list(session.execute(stmt).scalars().all())
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@read_session
|
|
120
|
+
def get_scopes(account, *, session: "Session"):
|
|
121
|
+
""" get all scopes defined for an account.
|
|
122
|
+
|
|
123
|
+
:param account: the account name to list the scopes of.
|
|
124
|
+
:param session: The database session in use.
|
|
125
|
+
|
|
126
|
+
:returns: a list of all scope names for this account.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
stmt = select(
|
|
130
|
+
models.Account
|
|
131
|
+
).where(
|
|
132
|
+
models.Account.account == account
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
if session.execute(stmt).first() is None:
|
|
136
|
+
raise AccountNotFound('Account ID \'%s\' does not exist' % account)
|
|
137
|
+
|
|
138
|
+
stmt = select(
|
|
139
|
+
models.Scope.scope
|
|
140
|
+
).where(
|
|
141
|
+
and_(models.Scope.account == account,
|
|
142
|
+
models.Scope.status != ScopeStatus.DELETED)
|
|
143
|
+
)
|
|
144
|
+
return session.execute(stmt).scalars().all()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@read_session
|
|
148
|
+
def check_scope(scope_to_check, *, session: "Session"):
|
|
149
|
+
""" check to see if scope exists.
|
|
150
|
+
|
|
151
|
+
:param scope: the scope to check.
|
|
152
|
+
:param session: The database session in use.
|
|
153
|
+
|
|
154
|
+
:returns: True or false
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
stmt = select(
|
|
158
|
+
models.Scope
|
|
159
|
+
).where(
|
|
160
|
+
models.Scope.scope == scope_to_check
|
|
161
|
+
)
|
|
162
|
+
return bool(session.execute(stmt).scalar())
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@read_session
|
|
166
|
+
def is_scope_owner(scope, account, *, session: "Session"):
|
|
167
|
+
""" check to see if account owns the scope.
|
|
168
|
+
|
|
169
|
+
:param scope: the scope to check.
|
|
170
|
+
:param account: the account to check.
|
|
171
|
+
:param session: The database session in use.
|
|
172
|
+
|
|
173
|
+
:returns: True or false
|
|
174
|
+
"""
|
|
175
|
+
stmt = select(
|
|
176
|
+
models.Scope
|
|
177
|
+
).where(
|
|
178
|
+
and_(models.Scope.scope == scope,
|
|
179
|
+
models.Scope.account == account)
|
|
180
|
+
)
|
|
181
|
+
return bool(session.execute(stmt).scalar())
|
|
@@ -0,0 +1,362 @@
|
|
|
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 datetime
|
|
16
|
+
import logging
|
|
17
|
+
import re
|
|
18
|
+
from configparser import NoOptionError, NoSectionError
|
|
19
|
+
from json import dumps
|
|
20
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
21
|
+
|
|
22
|
+
from sqlalchemy import and_, delete, func, select
|
|
23
|
+
from sqlalchemy.exc import IntegrityError, NoResultFound, StatementError
|
|
24
|
+
from sqlalchemy.orm import aliased
|
|
25
|
+
|
|
26
|
+
from rucio.common.config import config_get_bool
|
|
27
|
+
from rucio.common.exception import RucioException, SubscriptionDuplicate, SubscriptionNotFound
|
|
28
|
+
from rucio.db.sqla import models
|
|
29
|
+
from rucio.db.sqla.constants import RuleState, SubscriptionState
|
|
30
|
+
from rucio.db.sqla.session import read_session, stream_session, transactional_session
|
|
31
|
+
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from collections.abc import Callable, Iterator
|
|
34
|
+
|
|
35
|
+
from sqlalchemy.orm import Session
|
|
36
|
+
|
|
37
|
+
from rucio.common.types import InternalAccount
|
|
38
|
+
LoggerFunction = Callable[..., Any]
|
|
39
|
+
SubscriptionType = dict
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@transactional_session
|
|
43
|
+
def add_subscription(name: str,
|
|
44
|
+
account: "InternalAccount",
|
|
45
|
+
filter_: str,
|
|
46
|
+
replication_rules: str,
|
|
47
|
+
comments: str,
|
|
48
|
+
lifetime: Optional[int] = None,
|
|
49
|
+
retroactive: Optional[bool] = False,
|
|
50
|
+
dry_run: Optional[bool] = False,
|
|
51
|
+
priority: Optional[int] = 3,
|
|
52
|
+
*, session: "Session") -> str:
|
|
53
|
+
"""
|
|
54
|
+
Adds a new subscription which will be verified against every new added file and dataset
|
|
55
|
+
|
|
56
|
+
:param account: Account identifier
|
|
57
|
+
:type account: String
|
|
58
|
+
:param name: Name of the subscription
|
|
59
|
+
:type name: String
|
|
60
|
+
:param filter_: Dictionary of attributes by which the input data should be filtered
|
|
61
|
+
**Example**: ``{'dsn': 'data11_hi*.express_express.*,data11_hi*physics_MinBiasOverlay*', 'account': 'tzero'}``
|
|
62
|
+
:type filter_: Dict
|
|
63
|
+
:param replication_rules: Replication rules to be set : Dictionary with keys copies, rse_expression, weight, rse_expression
|
|
64
|
+
:type replication_rules: Dict
|
|
65
|
+
:param comments: Comments for the subscription
|
|
66
|
+
:type comments: String
|
|
67
|
+
:param lifetime: Subscription's lifetime (days)
|
|
68
|
+
:type lifetime: Integer or None
|
|
69
|
+
:param retroactive: Flag to know if the subscription should be applied on previous data
|
|
70
|
+
:type retroactive: Boolean
|
|
71
|
+
:param dry_run: Just print the subscriptions actions without actually executing them (Useful if retroactive flag is set)
|
|
72
|
+
:type dry_run: Boolean
|
|
73
|
+
:param priority: The priority of the subscription
|
|
74
|
+
:type priority: Integer
|
|
75
|
+
:param session: The database session in use.
|
|
76
|
+
|
|
77
|
+
:returns: The subscriptionid
|
|
78
|
+
"""
|
|
79
|
+
try:
|
|
80
|
+
keep_history = config_get_bool('subscriptions', 'keep_history')
|
|
81
|
+
except (NoOptionError, NoSectionError, RuntimeError):
|
|
82
|
+
keep_history = False
|
|
83
|
+
|
|
84
|
+
retroactive = bool(retroactive) # Force boolean type, necessary for strict SQL
|
|
85
|
+
state = SubscriptionState.ACTIVE
|
|
86
|
+
if retroactive:
|
|
87
|
+
state = SubscriptionState.NEW
|
|
88
|
+
if lifetime:
|
|
89
|
+
date_lifetime = datetime.datetime.utcnow() + datetime.timedelta(days=lifetime)
|
|
90
|
+
else:
|
|
91
|
+
date_lifetime = None
|
|
92
|
+
new_subscription = models.Subscription(name=name,
|
|
93
|
+
filter=filter_,
|
|
94
|
+
account=account,
|
|
95
|
+
replication_rules=replication_rules,
|
|
96
|
+
state=state,
|
|
97
|
+
lifetime=date_lifetime,
|
|
98
|
+
retroactive=retroactive,
|
|
99
|
+
policyid=priority, comments=comments)
|
|
100
|
+
if keep_history:
|
|
101
|
+
subscription_history = models.SubscriptionHistory(id=new_subscription.id,
|
|
102
|
+
name=new_subscription.name,
|
|
103
|
+
filter=new_subscription.filter,
|
|
104
|
+
account=new_subscription.account,
|
|
105
|
+
replication_rules=new_subscription.replication_rules,
|
|
106
|
+
state=new_subscription.state,
|
|
107
|
+
lifetime=new_subscription.lifetime,
|
|
108
|
+
retroactive=new_subscription.retroactive,
|
|
109
|
+
policyid=new_subscription.policyid,
|
|
110
|
+
comments=new_subscription.comments,
|
|
111
|
+
created_at=datetime.datetime.utcnow(),
|
|
112
|
+
updated_at=datetime.datetime.utcnow())
|
|
113
|
+
try:
|
|
114
|
+
new_subscription.save(session=session)
|
|
115
|
+
if keep_history:
|
|
116
|
+
subscription_history.save(session=session)
|
|
117
|
+
except IntegrityError as error:
|
|
118
|
+
if re.match('.*IntegrityError.*ORA-00001: unique constraint.*SUBSCRIPTIONS_PK.*violated.*', error.args[0])\
|
|
119
|
+
or re.match(".*IntegrityError.*UNIQUE constraint failed: subscriptions.name, subscriptions.account.*", error.args[0])\
|
|
120
|
+
or re.match('.*IntegrityError.*columns? name.*account.*not unique.*', error.args[0]) \
|
|
121
|
+
or re.match('.*IntegrityError.*ORA-00001: unique constraint.*SUBSCRIPTIONS_NAME_ACCOUNT_UQ.*violated.*', error.args[0])\
|
|
122
|
+
or re.match('.*IntegrityError.*1062.*Duplicate entry.*', error.args[0]) \
|
|
123
|
+
or re.match('.*IntegrityError.*duplicate key value violates unique constraint.*', error.args[0]) \
|
|
124
|
+
or re.match('.*UniqueViolation.*duplicate key value violates unique constraint.*', error.args[0]):
|
|
125
|
+
raise SubscriptionDuplicate('Subscription \'%s\' owned by \'%s\' already exists!' % (name, account))
|
|
126
|
+
raise RucioException(error.args)
|
|
127
|
+
return str(new_subscription.id)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@transactional_session
|
|
131
|
+
def update_subscription(name: str,
|
|
132
|
+
account: "InternalAccount",
|
|
133
|
+
metadata: dict,
|
|
134
|
+
*, session: "Session") -> None:
|
|
135
|
+
"""
|
|
136
|
+
Updates a subscription
|
|
137
|
+
|
|
138
|
+
:param name: Name of the subscription
|
|
139
|
+
:type name: String
|
|
140
|
+
:param account: Account identifier
|
|
141
|
+
:type account: String
|
|
142
|
+
:param metadata: Dictionary of metadata to update. Supported keys : filter, replication_rules, comments, lifetime, retroactive, dry_run, priority, last_processed
|
|
143
|
+
:type metadata: Dict
|
|
144
|
+
:param session: The database session in use.
|
|
145
|
+
|
|
146
|
+
:raises: SubscriptionNotFound if subscription is not found
|
|
147
|
+
"""
|
|
148
|
+
try:
|
|
149
|
+
keep_history = config_get_bool('subscriptions', 'keep_history')
|
|
150
|
+
except (NoOptionError, NoSectionError, RuntimeError):
|
|
151
|
+
keep_history = False
|
|
152
|
+
values: dict[str, Any] = {'state': SubscriptionState.UPDATED}
|
|
153
|
+
if 'filter' in metadata and metadata['filter']:
|
|
154
|
+
values['filter'] = dumps(metadata['filter'])
|
|
155
|
+
if 'replication_rules' in metadata and metadata['replication_rules']:
|
|
156
|
+
values['replication_rules'] = dumps(metadata['replication_rules'])
|
|
157
|
+
if 'lifetime' in metadata and metadata['lifetime']:
|
|
158
|
+
values['lifetime'] = datetime.datetime.utcnow() + datetime.timedelta(days=float(metadata['lifetime']))
|
|
159
|
+
if 'retroactive' in metadata and metadata['retroactive']:
|
|
160
|
+
values['retroactive'] = metadata['retroactive']
|
|
161
|
+
if 'dry_run' in metadata and metadata['dry_run']:
|
|
162
|
+
values['dry_run'] = metadata['dry_run']
|
|
163
|
+
if 'comments' in metadata and metadata['comments']:
|
|
164
|
+
values['comments'] = metadata['comments']
|
|
165
|
+
if 'priority' in metadata and metadata['priority']:
|
|
166
|
+
values['policyid'] = metadata['priority']
|
|
167
|
+
if 'last_processed' in metadata and metadata['last_processed']:
|
|
168
|
+
values['last_processed'] = metadata['last_processed']
|
|
169
|
+
if 'state' in metadata and metadata['state'] == SubscriptionState.INACTIVE:
|
|
170
|
+
values['state'] = SubscriptionState.INACTIVE
|
|
171
|
+
values['expired_at'] = datetime.datetime.utcnow()
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
stmt = select(
|
|
175
|
+
models.Subscription
|
|
176
|
+
).where(
|
|
177
|
+
and_(models.Subscription.name == name,
|
|
178
|
+
models.Subscription.account == account)
|
|
179
|
+
)
|
|
180
|
+
subscription = session.execute(stmt).scalar_one()
|
|
181
|
+
|
|
182
|
+
# To avoid update in the subscription history table whenever last processed field is changed
|
|
183
|
+
current_subscription_state = subscription.to_dict()
|
|
184
|
+
new_subscription_state = values.copy()
|
|
185
|
+
|
|
186
|
+
for key in ["updated_at", "last_processed"]:
|
|
187
|
+
new_subscription_state.pop(key, "None")
|
|
188
|
+
current_subscription_state.pop(key, "None")
|
|
189
|
+
|
|
190
|
+
subscription.update(values)
|
|
191
|
+
if keep_history and current_subscription_state != new_subscription_state:
|
|
192
|
+
subscription_history = models.SubscriptionHistory(id=subscription.id,
|
|
193
|
+
name=subscription.name,
|
|
194
|
+
filter=subscription.filter,
|
|
195
|
+
account=subscription.account,
|
|
196
|
+
replication_rules=subscription.replication_rules,
|
|
197
|
+
state=subscription.state,
|
|
198
|
+
lifetime=subscription.lifetime,
|
|
199
|
+
retroactive=subscription.retroactive,
|
|
200
|
+
policyid=subscription.policyid,
|
|
201
|
+
comments=subscription.comments,
|
|
202
|
+
last_processed=subscription.last_processed,
|
|
203
|
+
expired_at=subscription.expired_at,
|
|
204
|
+
updated_at=datetime.datetime.utcnow(),
|
|
205
|
+
created_at=subscription.created_at)
|
|
206
|
+
subscription_history.save(session=session)
|
|
207
|
+
except NoResultFound:
|
|
208
|
+
raise SubscriptionNotFound(f"Subscription for account '{account}' named '{name}' not found")
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@stream_session
|
|
212
|
+
def list_subscriptions(name: Optional[str] = None,
|
|
213
|
+
account: "Optional[InternalAccount]" = None,
|
|
214
|
+
state: Optional[SubscriptionState] = None,
|
|
215
|
+
*, session: "Session",
|
|
216
|
+
logger: "LoggerFunction" = logging.log) -> "Iterator[SubscriptionType]":
|
|
217
|
+
"""
|
|
218
|
+
Returns a dictionary with the subscription information :
|
|
219
|
+
Examples: ``{'status': 'INACTIVE/ACTIVE/BROKEN', 'last_modified_date': ...}``
|
|
220
|
+
|
|
221
|
+
:param name: Name of the subscription
|
|
222
|
+
:type name: String
|
|
223
|
+
:param account: Account identifier
|
|
224
|
+
:type account: String
|
|
225
|
+
:param session: The database session in use.
|
|
226
|
+
:param logger: Optional decorated logger that can be passed from the calling daemons or servers.
|
|
227
|
+
|
|
228
|
+
:returns: Dictionary containing subscription parameter
|
|
229
|
+
:rtype: Dict
|
|
230
|
+
:raises: exception.NotFound if subscription is not found
|
|
231
|
+
"""
|
|
232
|
+
stmt = select(
|
|
233
|
+
models.Subscription
|
|
234
|
+
)
|
|
235
|
+
try:
|
|
236
|
+
if name:
|
|
237
|
+
stmt = stmt.where(
|
|
238
|
+
models.Subscription.name == name
|
|
239
|
+
)
|
|
240
|
+
if account:
|
|
241
|
+
if account.internal is not None and '*' in account.internal:
|
|
242
|
+
account_str = account.internal.replace('*', '%')
|
|
243
|
+
stmt = stmt.where(
|
|
244
|
+
models.Subscription.account.like(account_str)
|
|
245
|
+
)
|
|
246
|
+
else:
|
|
247
|
+
stmt = stmt.where(
|
|
248
|
+
models.Subscription.account == account
|
|
249
|
+
)
|
|
250
|
+
if state:
|
|
251
|
+
stmt = stmt.where(
|
|
252
|
+
models.Subscription.state == state
|
|
253
|
+
)
|
|
254
|
+
except IntegrityError as error:
|
|
255
|
+
logger(logging.ERROR, str(error))
|
|
256
|
+
raise RucioException(error.args)
|
|
257
|
+
found = False
|
|
258
|
+
for row in session.execute(stmt).scalars().all():
|
|
259
|
+
found = True
|
|
260
|
+
yield row.to_dict()
|
|
261
|
+
if not found:
|
|
262
|
+
raise SubscriptionNotFound(f"Subscription for account '{account}' named '{name}' not found")
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
@transactional_session
|
|
266
|
+
def delete_subscription(subscription_id: str, *, session: "Session") -> None:
|
|
267
|
+
"""
|
|
268
|
+
Deletes a subscription
|
|
269
|
+
|
|
270
|
+
:param subscription_id: Subscription identifier
|
|
271
|
+
:type subscription_id: String
|
|
272
|
+
"""
|
|
273
|
+
stmt = delete(
|
|
274
|
+
models.Subscription
|
|
275
|
+
).where(
|
|
276
|
+
models.Subscription.id == subscription_id
|
|
277
|
+
)
|
|
278
|
+
session.execute(stmt)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@stream_session
|
|
282
|
+
def list_subscription_rule_states(
|
|
283
|
+
name: Optional[str] = None,
|
|
284
|
+
account: Optional["InternalAccount"] = None,
|
|
285
|
+
*,
|
|
286
|
+
session: "Session",
|
|
287
|
+
logger: "LoggerFunction" = logging.log
|
|
288
|
+
) -> "Iterator[tuple[InternalAccount, str, RuleState, int]]":
|
|
289
|
+
"""Returns a list of with the number of rules per state for a subscription.
|
|
290
|
+
|
|
291
|
+
:param name: Name of the subscription
|
|
292
|
+
:param account: Account identifier
|
|
293
|
+
:param session: The database session in use.
|
|
294
|
+
:param logger: Optional decorated logger that can be passed from the calling daemons or servers.
|
|
295
|
+
:returns: List with tuple (account, name, state, count)
|
|
296
|
+
"""
|
|
297
|
+
subscription = aliased(models.Subscription)
|
|
298
|
+
rule = aliased(models.ReplicationRule)
|
|
299
|
+
# count needs a label to allow conversion to dict (label name can be changed)
|
|
300
|
+
stmt = select(
|
|
301
|
+
subscription.account,
|
|
302
|
+
subscription.name,
|
|
303
|
+
rule.state,
|
|
304
|
+
func.count().label('count')
|
|
305
|
+
).join(
|
|
306
|
+
rule,
|
|
307
|
+
subscription.id == rule.subscription_id
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
try:
|
|
311
|
+
if name:
|
|
312
|
+
stmt = stmt.where(
|
|
313
|
+
subscription.name == name
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
if account:
|
|
317
|
+
if account.internal and '*' in account.internal:
|
|
318
|
+
account_str = account.internal.replace('*', '%')
|
|
319
|
+
stmt = stmt.where(
|
|
320
|
+
subscription.account.like(account_str)
|
|
321
|
+
)
|
|
322
|
+
else:
|
|
323
|
+
stmt = stmt.where(
|
|
324
|
+
subscription.account == account
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
except IntegrityError as error:
|
|
328
|
+
logger(logging.ERROR, str(error))
|
|
329
|
+
raise RucioException(error.args)
|
|
330
|
+
|
|
331
|
+
stmt = stmt.group_by(
|
|
332
|
+
subscription.account,
|
|
333
|
+
subscription.name,
|
|
334
|
+
rule.state
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
for row in session.execute(stmt).all():
|
|
338
|
+
yield row._tuple()
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
@read_session
|
|
342
|
+
def get_subscription_by_id(subscription_id: str, *, session: "Session") -> "SubscriptionType":
|
|
343
|
+
"""
|
|
344
|
+
Get a specific subscription by id.
|
|
345
|
+
|
|
346
|
+
:param subscription_id: The subscription_id to select.
|
|
347
|
+
:param session: The database session in use.
|
|
348
|
+
|
|
349
|
+
:raises: SubscriptionNotFound if no Subscription can be found.
|
|
350
|
+
"""
|
|
351
|
+
|
|
352
|
+
try:
|
|
353
|
+
stmt = select(
|
|
354
|
+
models.Subscription
|
|
355
|
+
).where(
|
|
356
|
+
models.Subscription.id == subscription_id
|
|
357
|
+
)
|
|
358
|
+
return session.execute(stmt).scalar_one().to_dict()
|
|
359
|
+
except NoResultFound:
|
|
360
|
+
raise SubscriptionNotFound('No subscription with the id %s found' % (subscription_id))
|
|
361
|
+
except StatementError:
|
|
362
|
+
raise RucioException('Badly formatted subscription id (%s)' % (subscription_id))
|