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
|
@@ -0,0 +1,36 @@
|
|
|
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 flask import Blueprint, Flask
|
|
16
|
+
|
|
17
|
+
from rucio.core.monitor import generate_prometheus_metrics
|
|
18
|
+
from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Metrics(ErrorHandlingMethodView):
|
|
22
|
+
def get(self):
|
|
23
|
+
return generate_prometheus_metrics()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def blueprint(standalone=False):
|
|
27
|
+
bp = Blueprint('metrics', __name__, url_prefix='/' if standalone else '/metrics')
|
|
28
|
+
metrics_view = Metrics.as_view('metrics')
|
|
29
|
+
bp.add_url_rule('/', view_func=metrics_view, methods=['get', ])
|
|
30
|
+
return bp
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def make_doc():
|
|
34
|
+
doc_app = Flask(__name__)
|
|
35
|
+
doc_app.register_blueprint(blueprint())
|
|
36
|
+
return doc_app
|
|
@@ -0,0 +1,97 @@
|
|
|
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 time
|
|
16
|
+
from typing import TYPE_CHECKING
|
|
17
|
+
|
|
18
|
+
from flask import Blueprint, Flask, request
|
|
19
|
+
from werkzeug.datastructures import Headers
|
|
20
|
+
|
|
21
|
+
from rucio.core.nongrid_trace import trace
|
|
22
|
+
from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, json_parameters, response_headers
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from typing import Optional
|
|
26
|
+
|
|
27
|
+
from rucio.web.rest.flaskapi.v1.types import HeadersType
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class XAODTrace(ErrorHandlingMethodView):
|
|
31
|
+
|
|
32
|
+
def get_headers(self) -> "Optional[HeadersType]":
|
|
33
|
+
headers = Headers()
|
|
34
|
+
headers.set('Content-Type', 'application/octet-stream')
|
|
35
|
+
headers.set('Access-Control-Allow-Origin', request.environ.get('HTTP_ORIGIN'))
|
|
36
|
+
headers.set('Access-Control-Allow-Headers', request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS'))
|
|
37
|
+
headers.set('Access-Control-Allow-Methods', '*')
|
|
38
|
+
headers.set('Access-Control-Allow-Credentials', 'true')
|
|
39
|
+
return headers
|
|
40
|
+
|
|
41
|
+
def post(self):
|
|
42
|
+
"""
|
|
43
|
+
---
|
|
44
|
+
summary: Trace endpoints
|
|
45
|
+
description: Trace endpoint used by the XAOD framework to post data access information.
|
|
46
|
+
tags:
|
|
47
|
+
- Nongrid traces
|
|
48
|
+
requestBody:
|
|
49
|
+
content:
|
|
50
|
+
application/json:
|
|
51
|
+
schema:
|
|
52
|
+
type: object
|
|
53
|
+
properties:
|
|
54
|
+
payload:
|
|
55
|
+
description: Dictionary containing the trace information.
|
|
56
|
+
type: object
|
|
57
|
+
responses:
|
|
58
|
+
201:
|
|
59
|
+
description: OK
|
|
60
|
+
content:
|
|
61
|
+
application/json:
|
|
62
|
+
schema:
|
|
63
|
+
type: string
|
|
64
|
+
enum: ["Created"]
|
|
65
|
+
400:
|
|
66
|
+
description: Cannot decode json data.
|
|
67
|
+
"""
|
|
68
|
+
headers = self.get_headers()
|
|
69
|
+
|
|
70
|
+
parameters = json_parameters()
|
|
71
|
+
|
|
72
|
+
# generate entry timestamp
|
|
73
|
+
parameters['timeentry'] = int(time.time())
|
|
74
|
+
|
|
75
|
+
# guess client IP
|
|
76
|
+
parameters['ip'] = request.headers.get('X-Forwarded-For', default=request.remote_addr)
|
|
77
|
+
|
|
78
|
+
trace(payload=parameters)
|
|
79
|
+
|
|
80
|
+
return 'Created', 201, headers
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def blueprint():
|
|
84
|
+
bp = Blueprint('nongrid_traces', __name__, url_prefix='/nongrid_traces')
|
|
85
|
+
|
|
86
|
+
xaod_trace_view = XAODTrace.as_view('xaod_trace')
|
|
87
|
+
bp.add_url_rule('/', view_func=xaod_trace_view, methods=['post', ])
|
|
88
|
+
|
|
89
|
+
bp.after_request(response_headers)
|
|
90
|
+
return bp
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def make_doc():
|
|
94
|
+
""" Only used for sphinx documentation """
|
|
95
|
+
doc_app = Flask(__name__)
|
|
96
|
+
doc_app.register_blueprint(blueprint())
|
|
97
|
+
return doc_app
|
|
@@ -0,0 +1,88 @@
|
|
|
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 typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
from flask import Blueprint, Flask, jsonify, request
|
|
18
|
+
from werkzeug.datastructures import Headers
|
|
19
|
+
|
|
20
|
+
from rucio import version
|
|
21
|
+
from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, check_accept_header_wrapper_flask, response_headers
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from typing import Optional
|
|
25
|
+
|
|
26
|
+
from rucio.web.rest.flaskapi.v1.types import HeadersType
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Ping(ErrorHandlingMethodView):
|
|
30
|
+
|
|
31
|
+
def get_headers(self) -> "Optional[HeadersType]":
|
|
32
|
+
headers = Headers()
|
|
33
|
+
headers.set('Access-Control-Allow-Origin', request.environ.get('HTTP_ORIGIN'))
|
|
34
|
+
headers.set('Access-Control-Allow-Headers', request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS'))
|
|
35
|
+
headers.set('Access-Control-Allow-Methods', '*')
|
|
36
|
+
headers.set('Access-Control-Allow-Credentials', 'true')
|
|
37
|
+
|
|
38
|
+
headers.set('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate')
|
|
39
|
+
headers.add('Cache-Control', 'post-check=0, pre-check=0')
|
|
40
|
+
headers.set('Pragma', 'no-cache')
|
|
41
|
+
return headers
|
|
42
|
+
|
|
43
|
+
@check_accept_header_wrapper_flask(['application/json'])
|
|
44
|
+
def get(self):
|
|
45
|
+
"""
|
|
46
|
+
---
|
|
47
|
+
summary: Ping
|
|
48
|
+
description: Ping the server and get data about it.
|
|
49
|
+
tags:
|
|
50
|
+
- Ping
|
|
51
|
+
responses:
|
|
52
|
+
200:
|
|
53
|
+
description: OK
|
|
54
|
+
content:
|
|
55
|
+
application/json:
|
|
56
|
+
schema:
|
|
57
|
+
type: object
|
|
58
|
+
properties:
|
|
59
|
+
version:
|
|
60
|
+
description: The server version.
|
|
61
|
+
type: string
|
|
62
|
+
406:
|
|
63
|
+
description: Not acceptable
|
|
64
|
+
"""
|
|
65
|
+
headers = self.get_headers()
|
|
66
|
+
response = jsonify(version=version.version_string())
|
|
67
|
+
response.headers.extend(headers)
|
|
68
|
+
return response
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def blueprint(standalone=False, with_doc=False):
|
|
72
|
+
bp = Blueprint('ping', __name__, url_prefix='/' if standalone else '/ping')
|
|
73
|
+
|
|
74
|
+
ping_view = Ping.as_view('ping')
|
|
75
|
+
if not with_doc:
|
|
76
|
+
# rule without trailing slash needs to be added before rule with trailing slash
|
|
77
|
+
bp.add_url_rule('', view_func=ping_view, methods=['get', ])
|
|
78
|
+
bp.add_url_rule('/', view_func=ping_view, methods=['get', ])
|
|
79
|
+
|
|
80
|
+
bp.after_request(response_headers)
|
|
81
|
+
return bp
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def make_doc():
|
|
85
|
+
""" Only used for sphinx documentation to add the prefix """
|
|
86
|
+
doc_app = Flask(__name__)
|
|
87
|
+
doc_app.register_blueprint(blueprint(with_doc=True))
|
|
88
|
+
return doc_app
|
|
@@ -0,0 +1,366 @@
|
|
|
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 itertools
|
|
16
|
+
from typing import TYPE_CHECKING
|
|
17
|
+
|
|
18
|
+
from flask import Blueprint, Flask, redirect, request
|
|
19
|
+
from werkzeug.datastructures import Headers
|
|
20
|
+
|
|
21
|
+
from rucio.common.exception import DataIdentifierNotFound, ReplicaNotFound, SortingAlgorithmNotSupported
|
|
22
|
+
from rucio.core.replica_sorter import site_selector, sort_replicas
|
|
23
|
+
from rucio.gateway.replica import list_replicas
|
|
24
|
+
from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, check_accept_header_wrapper_flask, extract_vo, generate_http_error_flask, parse_scope_name, try_stream
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from typing import Optional
|
|
28
|
+
|
|
29
|
+
from rucio.common.types import IPDict, ReplicaDict
|
|
30
|
+
from rucio.web.rest.flaskapi.v1.types import HeadersType
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class MetaLinkRedirector(ErrorHandlingMethodView):
|
|
34
|
+
|
|
35
|
+
def get_headers(self) -> "Optional[HeadersType]":
|
|
36
|
+
headers = Headers()
|
|
37
|
+
headers.set('Access-Control-Allow-Origin', request.environ.get('HTTP_ORIGIN'))
|
|
38
|
+
headers.set('Access-Control-Allow-Headers', request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS'))
|
|
39
|
+
headers.set('Access-Control-Allow-Methods', '*')
|
|
40
|
+
headers.set('Access-Control-Allow-Credentials', 'true')
|
|
41
|
+
return headers
|
|
42
|
+
|
|
43
|
+
@check_accept_header_wrapper_flask(['application/metalink4+xml'])
|
|
44
|
+
def get(self, scope_name):
|
|
45
|
+
"""
|
|
46
|
+
---
|
|
47
|
+
summary: Metalink redirect
|
|
48
|
+
description: Get Metalink redirect.
|
|
49
|
+
tags:
|
|
50
|
+
- Redirect
|
|
51
|
+
parameters:
|
|
52
|
+
- name: scope_name
|
|
53
|
+
in: path
|
|
54
|
+
description: The data identifier (scope)/(name).
|
|
55
|
+
schema:
|
|
56
|
+
type: string
|
|
57
|
+
style: simple
|
|
58
|
+
- name: ip
|
|
59
|
+
in: query
|
|
60
|
+
description: The client ip.
|
|
61
|
+
schema:
|
|
62
|
+
type: string
|
|
63
|
+
style: simple
|
|
64
|
+
required: false
|
|
65
|
+
- name: fqdn
|
|
66
|
+
in: query
|
|
67
|
+
schema:
|
|
68
|
+
type: string
|
|
69
|
+
style: simple
|
|
70
|
+
required: false
|
|
71
|
+
- name: site
|
|
72
|
+
in: query
|
|
73
|
+
schema:
|
|
74
|
+
type: string
|
|
75
|
+
style: simple
|
|
76
|
+
required: false
|
|
77
|
+
- name: schemes
|
|
78
|
+
in: query
|
|
79
|
+
schema:
|
|
80
|
+
type: array
|
|
81
|
+
style: simple
|
|
82
|
+
required: false
|
|
83
|
+
- name: select
|
|
84
|
+
in: query
|
|
85
|
+
schema:
|
|
86
|
+
type: string
|
|
87
|
+
style: simple
|
|
88
|
+
required: false
|
|
89
|
+
- name: sort
|
|
90
|
+
in: query
|
|
91
|
+
schema:
|
|
92
|
+
type: string
|
|
93
|
+
style: simple
|
|
94
|
+
required: false
|
|
95
|
+
responses:
|
|
96
|
+
200:
|
|
97
|
+
description: OK
|
|
98
|
+
content:
|
|
99
|
+
application/metalink4+xml:
|
|
100
|
+
schema:
|
|
101
|
+
description: The metalink file.
|
|
102
|
+
type: string
|
|
103
|
+
401:
|
|
104
|
+
description: Invalid Auth Token
|
|
105
|
+
404:
|
|
106
|
+
description: Rse or did not found
|
|
107
|
+
406:
|
|
108
|
+
description: Not acceptable
|
|
109
|
+
"""
|
|
110
|
+
headers = self.get_headers()
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
scope, name = parse_scope_name(scope_name, extract_vo(request.headers))
|
|
114
|
+
except ValueError as error:
|
|
115
|
+
return generate_http_error_flask(400, error, headers=headers)
|
|
116
|
+
|
|
117
|
+
# set the correct client IP
|
|
118
|
+
client_ip = request.headers.get('X-Forwarded-For', default=request.remote_addr)
|
|
119
|
+
|
|
120
|
+
client_location: 'IPDict' = {
|
|
121
|
+
'ip': request.args.get('ip', default=client_ip),
|
|
122
|
+
'fqdn': request.args.get('fqdn', default=None),
|
|
123
|
+
'site': request.args.get('site', default=None),
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
dids = [{'scope': scope, 'name': name}]
|
|
127
|
+
schemes = request.args.getlist('schemes') or ['http', 'https', 'root', 'gsiftp', 'srm', 'davs']
|
|
128
|
+
sortby = request.args.get('select', default=None)
|
|
129
|
+
sortby = request.args.get('sort', default=sortby)
|
|
130
|
+
|
|
131
|
+
# get vo if given
|
|
132
|
+
vo = extract_vo(request.headers)
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
replicas_iter = list_replicas(dids=dids, schemes=schemes, client_location=client_location, vo=vo)
|
|
136
|
+
try:
|
|
137
|
+
first = next(replicas_iter)
|
|
138
|
+
except StopIteration:
|
|
139
|
+
return 'no redirection possible - cannot find the DID', 404
|
|
140
|
+
|
|
141
|
+
def generate():
|
|
142
|
+
# first, set the appropriate content type, and stream the header
|
|
143
|
+
yield '<?xml version="1.0" encoding="UTF-8"?>\n<metalink xmlns="urn:ietf:params:xml:ns:metalink">\n'
|
|
144
|
+
|
|
145
|
+
# iteratively stream the XML per file
|
|
146
|
+
for rfile in itertools.chain((first,), replicas_iter):
|
|
147
|
+
replicas = []
|
|
148
|
+
dictreplica = {}
|
|
149
|
+
for rse in rfile['rses']:
|
|
150
|
+
for replica in rfile['rses'][rse]:
|
|
151
|
+
replicas.append(replica)
|
|
152
|
+
dictreplica[replica] = rse
|
|
153
|
+
|
|
154
|
+
# stream metadata
|
|
155
|
+
yield ' <file name="' + rfile['name'] + '">\n'
|
|
156
|
+
yield ' <identity>' + rfile['scope'] + ':' + rfile['name'] + '</identity>\n'
|
|
157
|
+
|
|
158
|
+
if rfile['adler32'] is not None:
|
|
159
|
+
yield ' <hash type="adler32">' + rfile['adler32'] + '</hash>\n'
|
|
160
|
+
if rfile['md5'] is not None:
|
|
161
|
+
yield ' <hash type="md5">' + rfile['md5'] + '</hash>\n'
|
|
162
|
+
|
|
163
|
+
yield ' <size>' + str(rfile['bytes']) + '</size>\n'
|
|
164
|
+
|
|
165
|
+
yield f' <glfn name="/atlas/rucio/{rfile["scope"]}:{rfile["name"]}">'
|
|
166
|
+
yield '</glfn>\n'
|
|
167
|
+
|
|
168
|
+
replicas = sort_replicas(dictreplica, client_location, selection=sortby)
|
|
169
|
+
|
|
170
|
+
# stream URLs
|
|
171
|
+
idx = 1
|
|
172
|
+
for replica in replicas:
|
|
173
|
+
yield ' <url location="' + str(dictreplica[replica]) + '" priority="' + str(idx) + '">' + replica + '</url>\n'
|
|
174
|
+
idx += 1
|
|
175
|
+
|
|
176
|
+
yield ' </file>\n'
|
|
177
|
+
|
|
178
|
+
# don't forget to send the metalink footer
|
|
179
|
+
yield '</metalink>\n'
|
|
180
|
+
|
|
181
|
+
return try_stream(generate(), content_type='application/metalink4+xml')
|
|
182
|
+
except (DataIdentifierNotFound, ReplicaNotFound, SortingAlgorithmNotSupported) as error:
|
|
183
|
+
return generate_http_error_flask(404, error, headers=headers)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class HeaderRedirector(ErrorHandlingMethodView):
|
|
187
|
+
|
|
188
|
+
def get_headers(self) -> "Optional[HeadersType]":
|
|
189
|
+
headers = Headers()
|
|
190
|
+
headers.set('Access-Control-Allow-Origin', request.environ.get('HTTP_ORIGIN'))
|
|
191
|
+
headers.set('Access-Control-Allow-Headers', request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS'))
|
|
192
|
+
headers.set('Access-Control-Allow-Methods', '*')
|
|
193
|
+
headers.set('Access-Control-Allow-Credentials', 'true')
|
|
194
|
+
return headers
|
|
195
|
+
|
|
196
|
+
def get(self, scope_name):
|
|
197
|
+
"""
|
|
198
|
+
---
|
|
199
|
+
summary: Header redirect
|
|
200
|
+
description: Get the header redirect.
|
|
201
|
+
tags:
|
|
202
|
+
- Redirect
|
|
203
|
+
parameters:
|
|
204
|
+
- name: scope_name
|
|
205
|
+
in: path
|
|
206
|
+
description: The data identifier (scope)/(name).
|
|
207
|
+
schema:
|
|
208
|
+
type: string
|
|
209
|
+
style: simple
|
|
210
|
+
- name: ip
|
|
211
|
+
in: query
|
|
212
|
+
description: The client ip.
|
|
213
|
+
schema:
|
|
214
|
+
type: string
|
|
215
|
+
style: simple
|
|
216
|
+
required: false
|
|
217
|
+
- name: fqdn
|
|
218
|
+
in: query
|
|
219
|
+
schema:
|
|
220
|
+
type: string
|
|
221
|
+
style: simple
|
|
222
|
+
required: false
|
|
223
|
+
- name: site
|
|
224
|
+
in: query
|
|
225
|
+
schema:
|
|
226
|
+
type: string
|
|
227
|
+
style: simple
|
|
228
|
+
required: false
|
|
229
|
+
- name: schemes
|
|
230
|
+
in: query
|
|
231
|
+
schema:
|
|
232
|
+
type: array
|
|
233
|
+
style: simple
|
|
234
|
+
required: false
|
|
235
|
+
- name: select
|
|
236
|
+
in: query
|
|
237
|
+
schema:
|
|
238
|
+
type: string
|
|
239
|
+
style: simple
|
|
240
|
+
required: false
|
|
241
|
+
- name: sort
|
|
242
|
+
in: query
|
|
243
|
+
schema:
|
|
244
|
+
type: string
|
|
245
|
+
style: simple
|
|
246
|
+
required: false
|
|
247
|
+
- name: rse
|
|
248
|
+
in: query
|
|
249
|
+
schema:
|
|
250
|
+
type: string
|
|
251
|
+
style: simple
|
|
252
|
+
required: false
|
|
253
|
+
responses:
|
|
254
|
+
200:
|
|
255
|
+
description: OK
|
|
256
|
+
303:
|
|
257
|
+
description: OK
|
|
258
|
+
content:
|
|
259
|
+
application/json:
|
|
260
|
+
schema:
|
|
261
|
+
description: The redirect url.
|
|
262
|
+
type: string
|
|
263
|
+
401:
|
|
264
|
+
description: Invalid Auth Token
|
|
265
|
+
404:
|
|
266
|
+
description: Rse or did not found
|
|
267
|
+
"""
|
|
268
|
+
headers = self.get_headers()
|
|
269
|
+
|
|
270
|
+
try:
|
|
271
|
+
scope, name = parse_scope_name(scope_name, extract_vo(request.headers))
|
|
272
|
+
except ValueError as error:
|
|
273
|
+
return generate_http_error_flask(400, error, headers=headers)
|
|
274
|
+
|
|
275
|
+
try:
|
|
276
|
+
client_ip = request.headers.get('X-Forwarded-For', default=request.remote_addr)
|
|
277
|
+
|
|
278
|
+
client_location: 'IPDict' = {
|
|
279
|
+
'ip': request.args.get('ip', default=client_ip),
|
|
280
|
+
'fqdn': request.args.get('fqdn', default=None),
|
|
281
|
+
'site': request.args.get('site', default=None),
|
|
282
|
+
}
|
|
283
|
+
# use the default HTTP protocols if no scheme is given
|
|
284
|
+
schemes = request.args.getlist('schemes') or ['davs', 'https', 's3']
|
|
285
|
+
sortby = request.args.get('select', default='random')
|
|
286
|
+
sortby = request.args.get('sort', default=sortby)
|
|
287
|
+
rse = request.args.get('rse', default=None)
|
|
288
|
+
site = request.args.get('site', default=None)
|
|
289
|
+
|
|
290
|
+
# correctly forward the schemes and select to potential metalink followups
|
|
291
|
+
cleaned_url = request.environ.get('REQUEST_URI').split('?')[0]
|
|
292
|
+
|
|
293
|
+
headers.set('Link', f'<{cleaned_url}/metalink?schemes={",".join(schemes)}&select={sortby}>; rel=describedby; type="application/metalink+xml"')
|
|
294
|
+
|
|
295
|
+
# get vo if given
|
|
296
|
+
vo = extract_vo(request.headers)
|
|
297
|
+
|
|
298
|
+
replicas = list(
|
|
299
|
+
list_replicas( # type: ignore (session parameter missing)
|
|
300
|
+
dids=[{'scope': scope, 'name': name, 'type': 'FILE'}],
|
|
301
|
+
schemes=schemes,
|
|
302
|
+
client_location=client_location,
|
|
303
|
+
vo=vo
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
selected_url = None
|
|
308
|
+
for r in replicas:
|
|
309
|
+
if r['rses']:
|
|
310
|
+
dictreplica: dict[str, 'ReplicaDict'] = {}
|
|
311
|
+
|
|
312
|
+
if rse:
|
|
313
|
+
if rse in r['rses'] and r['rses'][rse]:
|
|
314
|
+
selected_url = r['rses'][rse][0]
|
|
315
|
+
else:
|
|
316
|
+
return 'no redirection possible - no valid RSE for HTTP redirection found', 404, headers
|
|
317
|
+
else:
|
|
318
|
+
|
|
319
|
+
for rep in r['rses']:
|
|
320
|
+
for replica in r['rses'][rep]:
|
|
321
|
+
# since this is HTTP-only redirection, and to ensure compatibility with as many http clients as possible
|
|
322
|
+
# forcibly replacement davs and s3 URLs to https
|
|
323
|
+
replica = replica.replace('davs://', 'https://').replace('s3://', 'https://')
|
|
324
|
+
dictreplica[replica] = rep
|
|
325
|
+
|
|
326
|
+
if not dictreplica:
|
|
327
|
+
return 'no redirection possible - no valid RSE for HTTP redirection found', 404, headers
|
|
328
|
+
|
|
329
|
+
elif site:
|
|
330
|
+
rep = site_selector(dictreplica, site, vo)
|
|
331
|
+
if rep:
|
|
332
|
+
selected_url = rep[0]
|
|
333
|
+
else:
|
|
334
|
+
return 'no redirection possible - no valid RSE for HTTP redirection found', 404, headers
|
|
335
|
+
else:
|
|
336
|
+
rep = sort_replicas(dictreplica, client_location, selection=sortby)
|
|
337
|
+
selected_url = rep[0]
|
|
338
|
+
|
|
339
|
+
if selected_url:
|
|
340
|
+
response = redirect(selected_url, code=303)
|
|
341
|
+
response.headers.extend(headers)
|
|
342
|
+
return response
|
|
343
|
+
|
|
344
|
+
return 'no redirection possible - file does not exist', 404, headers
|
|
345
|
+
except (ReplicaNotFound, SortingAlgorithmNotSupported) as error:
|
|
346
|
+
return generate_http_error_flask(404, error, headers=headers)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def blueprint(with_doc=False):
|
|
350
|
+
bp = Blueprint('redirect', __name__, url_prefix='/redirect')
|
|
351
|
+
|
|
352
|
+
metalink_redirector_view = MetaLinkRedirector.as_view('metalink_redirector')
|
|
353
|
+
bp.add_url_rule('/<path:scope_name>/metalink', view_func=metalink_redirector_view, methods=['get', ])
|
|
354
|
+
header_redirector_view = HeaderRedirector.as_view('header_redirector')
|
|
355
|
+
bp.add_url_rule('/<path:scope_name>', view_func=header_redirector_view, methods=['get', ])
|
|
356
|
+
if not with_doc:
|
|
357
|
+
bp.add_url_rule('/<path:scope_name>/', view_func=header_redirector_view, methods=['get', ])
|
|
358
|
+
|
|
359
|
+
return bp
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def make_doc():
|
|
363
|
+
""" Only used for sphinx documentation """
|
|
364
|
+
doc_app = Flask(__name__)
|
|
365
|
+
doc_app.register_blueprint(blueprint(with_doc=True))
|
|
366
|
+
return doc_app
|