rucio 32.8.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/__init__.py +18 -0
- rucio/alembicrevision.py +16 -0
- rucio/api/__init__.py +14 -0
- rucio/api/account.py +266 -0
- rucio/api/account_limit.py +287 -0
- rucio/api/authentication.py +302 -0
- rucio/api/config.py +218 -0
- rucio/api/credential.py +60 -0
- rucio/api/did.py +726 -0
- rucio/api/dirac.py +71 -0
- rucio/api/exporter.py +60 -0
- rucio/api/heartbeat.py +62 -0
- rucio/api/identity.py +160 -0
- rucio/api/importer.py +46 -0
- rucio/api/lifetime_exception.py +95 -0
- rucio/api/lock.py +131 -0
- rucio/api/meta.py +85 -0
- rucio/api/permission.py +72 -0
- rucio/api/quarantined_replica.py +69 -0
- rucio/api/replica.py +528 -0
- rucio/api/request.py +220 -0
- rucio/api/rse.py +601 -0
- rucio/api/rule.py +335 -0
- rucio/api/scope.py +89 -0
- rucio/api/subscription.py +255 -0
- rucio/api/temporary_did.py +49 -0
- rucio/api/vo.py +112 -0
- rucio/client/__init__.py +16 -0
- rucio/client/accountclient.py +413 -0
- rucio/client/accountlimitclient.py +155 -0
- rucio/client/baseclient.py +929 -0
- rucio/client/client.py +77 -0
- rucio/client/configclient.py +113 -0
- rucio/client/credentialclient.py +54 -0
- rucio/client/didclient.py +691 -0
- rucio/client/diracclient.py +48 -0
- rucio/client/downloadclient.py +1674 -0
- rucio/client/exportclient.py +44 -0
- rucio/client/fileclient.py +51 -0
- rucio/client/importclient.py +42 -0
- rucio/client/lifetimeclient.py +74 -0
- rucio/client/lockclient.py +99 -0
- rucio/client/metaclient.py +137 -0
- rucio/client/pingclient.py +45 -0
- rucio/client/replicaclient.py +444 -0
- rucio/client/requestclient.py +109 -0
- rucio/client/rseclient.py +664 -0
- rucio/client/ruleclient.py +287 -0
- rucio/client/scopeclient.py +88 -0
- rucio/client/subscriptionclient.py +161 -0
- rucio/client/touchclient.py +78 -0
- rucio/client/uploadclient.py +871 -0
- rucio/common/__init__.py +14 -0
- rucio/common/cache.py +74 -0
- rucio/common/config.py +796 -0
- rucio/common/constants.py +92 -0
- rucio/common/constraints.py +18 -0
- rucio/common/didtype.py +187 -0
- rucio/common/dumper/__init__.py +306 -0
- rucio/common/dumper/consistency.py +449 -0
- rucio/common/dumper/data_models.py +325 -0
- rucio/common/dumper/path_parsing.py +65 -0
- rucio/common/exception.py +1092 -0
- rucio/common/extra.py +37 -0
- rucio/common/logging.py +404 -0
- rucio/common/pcache.py +1387 -0
- rucio/common/policy.py +84 -0
- rucio/common/schema/__init__.py +143 -0
- rucio/common/schema/atlas.py +411 -0
- rucio/common/schema/belleii.py +406 -0
- rucio/common/schema/cms.py +478 -0
- rucio/common/schema/domatpc.py +399 -0
- rucio/common/schema/escape.py +424 -0
- rucio/common/schema/generic.py +431 -0
- rucio/common/schema/generic_multi_vo.py +410 -0
- rucio/common/schema/icecube.py +404 -0
- rucio/common/schema/lsst.py +423 -0
- rucio/common/stomp_utils.py +160 -0
- rucio/common/stopwatch.py +56 -0
- rucio/common/test_rucio_server.py +148 -0
- rucio/common/types.py +158 -0
- rucio/common/utils.py +1946 -0
- rucio/core/__init__.py +14 -0
- rucio/core/account.py +426 -0
- rucio/core/account_counter.py +171 -0
- rucio/core/account_limit.py +357 -0
- rucio/core/authentication.py +563 -0
- rucio/core/config.py +386 -0
- rucio/core/credential.py +218 -0
- rucio/core/did.py +3102 -0
- rucio/core/did_meta_plugins/__init__.py +250 -0
- rucio/core/did_meta_plugins/did_column_meta.py +326 -0
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +116 -0
- rucio/core/did_meta_plugins/filter_engine.py +573 -0
- rucio/core/did_meta_plugins/json_meta.py +215 -0
- rucio/core/did_meta_plugins/mongo_meta.py +199 -0
- rucio/core/did_meta_plugins/postgres_meta.py +317 -0
- rucio/core/dirac.py +208 -0
- rucio/core/distance.py +164 -0
- rucio/core/exporter.py +59 -0
- rucio/core/heartbeat.py +263 -0
- rucio/core/identity.py +290 -0
- rucio/core/importer.py +248 -0
- rucio/core/lifetime_exception.py +377 -0
- rucio/core/lock.py +474 -0
- rucio/core/message.py +241 -0
- rucio/core/meta.py +190 -0
- rucio/core/monitor.py +441 -0
- rucio/core/naming_convention.py +154 -0
- rucio/core/nongrid_trace.py +124 -0
- rucio/core/oidc.py +1339 -0
- rucio/core/permission/__init__.py +107 -0
- rucio/core/permission/atlas.py +1333 -0
- rucio/core/permission/belleii.py +1076 -0
- rucio/core/permission/cms.py +1166 -0
- rucio/core/permission/escape.py +1076 -0
- rucio/core/permission/generic.py +1128 -0
- rucio/core/permission/generic_multi_vo.py +1148 -0
- rucio/core/quarantined_replica.py +190 -0
- rucio/core/replica.py +3627 -0
- rucio/core/replica_sorter.py +368 -0
- rucio/core/request.py +2241 -0
- rucio/core/rse.py +1835 -0
- rucio/core/rse_counter.py +155 -0
- rucio/core/rse_expression_parser.py +460 -0
- rucio/core/rse_selector.py +277 -0
- rucio/core/rule.py +3419 -0
- rucio/core/rule_grouping.py +1473 -0
- rucio/core/scope.py +152 -0
- rucio/core/subscription.py +316 -0
- rucio/core/temporary_did.py +188 -0
- rucio/core/topology.py +448 -0
- rucio/core/trace.py +361 -0
- rucio/core/transfer.py +1233 -0
- rucio/core/vo.py +151 -0
- rucio/core/volatile_replica.py +123 -0
- rucio/daemons/__init__.py +14 -0
- rucio/daemons/abacus/__init__.py +14 -0
- rucio/daemons/abacus/account.py +106 -0
- rucio/daemons/abacus/collection_replica.py +113 -0
- rucio/daemons/abacus/rse.py +107 -0
- rucio/daemons/atropos/__init__.py +14 -0
- rucio/daemons/atropos/atropos.py +243 -0
- rucio/daemons/auditor/__init__.py +261 -0
- rucio/daemons/auditor/hdfs.py +86 -0
- rucio/daemons/auditor/srmdumps.py +284 -0
- rucio/daemons/automatix/__init__.py +14 -0
- rucio/daemons/automatix/automatix.py +281 -0
- rucio/daemons/badreplicas/__init__.py +14 -0
- rucio/daemons/badreplicas/minos.py +311 -0
- rucio/daemons/badreplicas/minos_temporary_expiration.py +173 -0
- rucio/daemons/badreplicas/necromancer.py +200 -0
- rucio/daemons/bb8/__init__.py +14 -0
- rucio/daemons/bb8/bb8.py +356 -0
- rucio/daemons/bb8/common.py +762 -0
- rucio/daemons/bb8/nuclei_background_rebalance.py +147 -0
- rucio/daemons/bb8/t2_background_rebalance.py +146 -0
- rucio/daemons/c3po/__init__.py +14 -0
- rucio/daemons/c3po/algorithms/__init__.py +14 -0
- rucio/daemons/c3po/algorithms/simple.py +131 -0
- rucio/daemons/c3po/algorithms/t2_free_space.py +125 -0
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +127 -0
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +279 -0
- rucio/daemons/c3po/c3po.py +342 -0
- rucio/daemons/c3po/collectors/__init__.py +14 -0
- rucio/daemons/c3po/collectors/agis.py +108 -0
- rucio/daemons/c3po/collectors/free_space.py +62 -0
- rucio/daemons/c3po/collectors/jedi_did.py +48 -0
- rucio/daemons/c3po/collectors/mock_did.py +46 -0
- rucio/daemons/c3po/collectors/network_metrics.py +63 -0
- rucio/daemons/c3po/collectors/workload.py +110 -0
- rucio/daemons/c3po/utils/__init__.py +14 -0
- rucio/daemons/c3po/utils/dataset_cache.py +40 -0
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +45 -0
- rucio/daemons/c3po/utils/expiring_list.py +63 -0
- rucio/daemons/c3po/utils/popularity.py +82 -0
- rucio/daemons/c3po/utils/timeseries.py +76 -0
- rucio/daemons/cache/__init__.py +14 -0
- rucio/daemons/cache/consumer.py +191 -0
- rucio/daemons/common.py +391 -0
- rucio/daemons/conveyor/__init__.py +14 -0
- rucio/daemons/conveyor/common.py +530 -0
- rucio/daemons/conveyor/finisher.py +492 -0
- rucio/daemons/conveyor/poller.py +372 -0
- rucio/daemons/conveyor/preparer.py +198 -0
- rucio/daemons/conveyor/receiver.py +206 -0
- rucio/daemons/conveyor/stager.py +127 -0
- rucio/daemons/conveyor/submitter.py +379 -0
- rucio/daemons/conveyor/throttler.py +468 -0
- rucio/daemons/follower/__init__.py +14 -0
- rucio/daemons/follower/follower.py +97 -0
- rucio/daemons/hermes/__init__.py +14 -0
- rucio/daemons/hermes/hermes.py +738 -0
- rucio/daemons/judge/__init__.py +14 -0
- rucio/daemons/judge/cleaner.py +149 -0
- rucio/daemons/judge/evaluator.py +172 -0
- rucio/daemons/judge/injector.py +154 -0
- rucio/daemons/judge/repairer.py +144 -0
- rucio/daemons/oauthmanager/__init__.py +14 -0
- rucio/daemons/oauthmanager/oauthmanager.py +199 -0
- rucio/daemons/reaper/__init__.py +14 -0
- rucio/daemons/reaper/dark_reaper.py +272 -0
- rucio/daemons/reaper/light_reaper.py +255 -0
- rucio/daemons/reaper/reaper.py +701 -0
- rucio/daemons/replicarecoverer/__init__.py +14 -0
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +487 -0
- rucio/daemons/storage/__init__.py +14 -0
- rucio/daemons/storage/consistency/__init__.py +14 -0
- rucio/daemons/storage/consistency/actions.py +753 -0
- rucio/daemons/tracer/__init__.py +14 -0
- rucio/daemons/tracer/kronos.py +513 -0
- rucio/daemons/transmogrifier/__init__.py +14 -0
- rucio/daemons/transmogrifier/transmogrifier.py +753 -0
- rucio/daemons/undertaker/__init__.py +14 -0
- rucio/daemons/undertaker/undertaker.py +137 -0
- rucio/db/__init__.py +14 -0
- rucio/db/sqla/__init__.py +38 -0
- rucio/db/sqla/constants.py +192 -0
- rucio/db/sqla/migrate_repo/__init__.py +14 -0
- rucio/db/sqla/migrate_repo/env.py +111 -0
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +71 -0
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +50 -0
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +61 -0
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +46 -0
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +93 -0
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +78 -0
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +46 -0
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +53 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +69 -0
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +42 -0
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +46 -0
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +61 -0
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +42 -0
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +141 -0
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +75 -0
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +75 -0
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +46 -0
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +51 -0
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +135 -0
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +65 -0
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +42 -0
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +66 -0
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +54 -0
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +46 -0
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +54 -0
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +39 -0
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +48 -0
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +48 -0
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +72 -0
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +46 -0
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +48 -0
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +48 -0
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +42 -0
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +69 -0
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +46 -0
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +78 -0
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +62 -0
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +74 -0
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +44 -0
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +67 -0
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +134 -0
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +58 -0
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +79 -0
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +61 -0
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +45 -0
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +46 -0
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +65 -0
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +42 -0
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +46 -0
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +46 -0
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +80 -0
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +61 -0
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +47 -0
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +46 -0
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +52 -0
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +42 -0
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +65 -0
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +46 -0
- rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +47 -0
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +45 -0
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +46 -0
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +48 -0
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +50 -0
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +48 -0
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +108 -0
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +57 -0
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +51 -0
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +50 -0
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +46 -0
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +42 -0
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +93 -0
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +73 -0
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +52 -0
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +45 -0
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +46 -0
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +54 -0
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +48 -0
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +70 -0
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +48 -0
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +95 -0
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +74 -0
- rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +78 -0
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +49 -0
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +124 -0
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +60 -0
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +53 -0
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +56 -0
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +67 -0
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +50 -0
- rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +46 -0
- rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +92 -0
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +42 -0
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +46 -0
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +147 -0
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +78 -0
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +53 -0
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +74 -0
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +56 -0
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +46 -0
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +68 -0
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +48 -0
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +149 -0
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +106 -0
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +45 -0
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +105 -0
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +52 -0
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +106 -0
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +30 -0
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +75 -0
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +49 -0
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +45 -0
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +38 -0
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +44 -0
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +46 -0
- rucio/db/sqla/models.py +1834 -0
- rucio/db/sqla/sautils.py +48 -0
- rucio/db/sqla/session.py +470 -0
- rucio/db/sqla/types.py +207 -0
- rucio/db/sqla/util.py +521 -0
- rucio/rse/__init__.py +97 -0
- rucio/rse/protocols/__init__.py +14 -0
- rucio/rse/protocols/cache.py +123 -0
- rucio/rse/protocols/dummy.py +112 -0
- rucio/rse/protocols/gfal.py +701 -0
- rucio/rse/protocols/globus.py +243 -0
- rucio/rse/protocols/gsiftp.py +93 -0
- rucio/rse/protocols/http_cache.py +83 -0
- rucio/rse/protocols/mock.py +124 -0
- rucio/rse/protocols/ngarc.py +210 -0
- rucio/rse/protocols/posix.py +251 -0
- rucio/rse/protocols/protocol.py +530 -0
- rucio/rse/protocols/rclone.py +365 -0
- rucio/rse/protocols/rfio.py +137 -0
- rucio/rse/protocols/srm.py +339 -0
- rucio/rse/protocols/ssh.py +414 -0
- rucio/rse/protocols/storm.py +207 -0
- rucio/rse/protocols/webdav.py +547 -0
- rucio/rse/protocols/xrootd.py +295 -0
- rucio/rse/rsemanager.py +752 -0
- rucio/tests/__init__.py +14 -0
- rucio/tests/common.py +244 -0
- rucio/tests/common_server.py +132 -0
- rucio/transfertool/__init__.py +14 -0
- rucio/transfertool/fts3.py +1484 -0
- rucio/transfertool/globus.py +200 -0
- rucio/transfertool/globus_library.py +182 -0
- rucio/transfertool/mock.py +81 -0
- rucio/transfertool/transfertool.py +212 -0
- rucio/vcsversion.py +11 -0
- rucio/version.py +46 -0
- rucio/web/__init__.py +14 -0
- rucio/web/rest/__init__.py +14 -0
- rucio/web/rest/flaskapi/__init__.py +14 -0
- rucio/web/rest/flaskapi/authenticated_bp.py +28 -0
- rucio/web/rest/flaskapi/v1/__init__.py +14 -0
- rucio/web/rest/flaskapi/v1/accountlimits.py +234 -0
- rucio/web/rest/flaskapi/v1/accounts.py +1088 -0
- rucio/web/rest/flaskapi/v1/archives.py +100 -0
- rucio/web/rest/flaskapi/v1/auth.py +1642 -0
- rucio/web/rest/flaskapi/v1/common.py +385 -0
- rucio/web/rest/flaskapi/v1/config.py +305 -0
- rucio/web/rest/flaskapi/v1/credentials.py +213 -0
- rucio/web/rest/flaskapi/v1/dids.py +2204 -0
- rucio/web/rest/flaskapi/v1/dirac.py +116 -0
- rucio/web/rest/flaskapi/v1/export.py +77 -0
- rucio/web/rest/flaskapi/v1/heartbeats.py +129 -0
- rucio/web/rest/flaskapi/v1/identities.py +263 -0
- rucio/web/rest/flaskapi/v1/import.py +133 -0
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +315 -0
- rucio/web/rest/flaskapi/v1/locks.py +360 -0
- rucio/web/rest/flaskapi/v1/main.py +83 -0
- rucio/web/rest/flaskapi/v1/meta.py +226 -0
- rucio/web/rest/flaskapi/v1/metrics.py +37 -0
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
- rucio/web/rest/flaskapi/v1/ping.py +89 -0
- rucio/web/rest/flaskapi/v1/redirect.py +366 -0
- rucio/web/rest/flaskapi/v1/replicas.py +1866 -0
- rucio/web/rest/flaskapi/v1/requests.py +841 -0
- rucio/web/rest/flaskapi/v1/rses.py +2204 -0
- rucio/web/rest/flaskapi/v1/rules.py +824 -0
- rucio/web/rest/flaskapi/v1/scopes.py +161 -0
- rucio/web/rest/flaskapi/v1/subscriptions.py +646 -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/tmp_dids.py +115 -0
- rucio/web/rest/flaskapi/v1/traces.py +100 -0
- rucio/web/rest/flaskapi/v1/vos.py +280 -0
- rucio/web/rest/main.py +19 -0
- rucio/web/rest/metrics.py +28 -0
- rucio-32.8.6.data/data/rucio/etc/alembic.ini.template +71 -0
- rucio-32.8.6.data/data/rucio/etc/alembic_offline.ini.template +74 -0
- rucio-32.8.6.data/data/rucio/etc/globus-config.yml.template +5 -0
- rucio-32.8.6.data/data/rucio/etc/ldap.cfg.template +30 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
- rucio-32.8.6.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
- rucio-32.8.6.data/data/rucio/etc/rucio.cfg.atlas.client.template +42 -0
- rucio-32.8.6.data/data/rucio/etc/rucio.cfg.template +257 -0
- rucio-32.8.6.data/data/rucio/etc/rucio_multi_vo.cfg.template +234 -0
- rucio-32.8.6.data/data/rucio/requirements.txt +55 -0
- rucio-32.8.6.data/data/rucio/tools/bootstrap.py +34 -0
- rucio-32.8.6.data/data/rucio/tools/merge_rucio_configs.py +147 -0
- rucio-32.8.6.data/data/rucio/tools/reset_database.py +40 -0
- rucio-32.8.6.data/scripts/rucio +2540 -0
- rucio-32.8.6.data/scripts/rucio-abacus-account +75 -0
- rucio-32.8.6.data/scripts/rucio-abacus-collection-replica +47 -0
- rucio-32.8.6.data/scripts/rucio-abacus-rse +79 -0
- rucio-32.8.6.data/scripts/rucio-admin +2434 -0
- rucio-32.8.6.data/scripts/rucio-atropos +61 -0
- rucio-32.8.6.data/scripts/rucio-auditor +199 -0
- rucio-32.8.6.data/scripts/rucio-automatix +51 -0
- rucio-32.8.6.data/scripts/rucio-bb8 +58 -0
- rucio-32.8.6.data/scripts/rucio-c3po +86 -0
- rucio-32.8.6.data/scripts/rucio-cache-client +135 -0
- rucio-32.8.6.data/scripts/rucio-cache-consumer +43 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-finisher +59 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-poller +67 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-preparer +38 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-receiver +44 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-stager +77 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-submitter +140 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-throttler +105 -0
- rucio-32.8.6.data/scripts/rucio-dark-reaper +54 -0
- rucio-32.8.6.data/scripts/rucio-dumper +159 -0
- rucio-32.8.6.data/scripts/rucio-follower +45 -0
- rucio-32.8.6.data/scripts/rucio-hermes +55 -0
- rucio-32.8.6.data/scripts/rucio-judge-cleaner +90 -0
- rucio-32.8.6.data/scripts/rucio-judge-evaluator +138 -0
- rucio-32.8.6.data/scripts/rucio-judge-injector +45 -0
- rucio-32.8.6.data/scripts/rucio-judge-repairer +45 -0
- rucio-32.8.6.data/scripts/rucio-kronos +45 -0
- rucio-32.8.6.data/scripts/rucio-light-reaper +53 -0
- rucio-32.8.6.data/scripts/rucio-minos +54 -0
- rucio-32.8.6.data/scripts/rucio-minos-temporary-expiration +51 -0
- rucio-32.8.6.data/scripts/rucio-necromancer +121 -0
- rucio-32.8.6.data/scripts/rucio-oauth-manager +64 -0
- rucio-32.8.6.data/scripts/rucio-reaper +84 -0
- rucio-32.8.6.data/scripts/rucio-replica-recoverer +249 -0
- rucio-32.8.6.data/scripts/rucio-storage-consistency-actions +75 -0
- rucio-32.8.6.data/scripts/rucio-transmogrifier +78 -0
- rucio-32.8.6.data/scripts/rucio-undertaker +77 -0
- rucio-32.8.6.dist-info/METADATA +83 -0
- rucio-32.8.6.dist-info/RECORD +481 -0
- rucio-32.8.6.dist-info/WHEEL +5 -0
- rucio-32.8.6.dist-info/licenses/AUTHORS.rst +94 -0
- rucio-32.8.6.dist-info/licenses/LICENSE +201 -0
- rucio-32.8.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
|
|
18
|
+
from rucio.common.utils import chunks
|
|
19
|
+
from rucio.db.sqla.constants import RequestState
|
|
20
|
+
from rucio.transfertool.transfertool import Transfertool, TransferToolBuilder, TransferStatusReport
|
|
21
|
+
from .globus_library import bulk_submit_xfer, submit_xfer, bulk_check_xfers
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def bulk_group_transfers(transfer_paths, policy='single', group_bulk=200):
|
|
25
|
+
"""
|
|
26
|
+
Group transfers in bulk based on certain criterias
|
|
27
|
+
|
|
28
|
+
:param transfer_paths: List of (potentially multihop) transfer paths to group. Each path is a list of single-hop transfers.
|
|
29
|
+
:param policy: Policy to use to group.
|
|
30
|
+
:param group_bulk: Bulk sizes.
|
|
31
|
+
:return: List of transfer groups
|
|
32
|
+
"""
|
|
33
|
+
if policy == 'single':
|
|
34
|
+
group_bulk = 1
|
|
35
|
+
|
|
36
|
+
grouped_jobs = []
|
|
37
|
+
for chunk in chunks(transfer_paths, group_bulk):
|
|
38
|
+
# Globus doesn't support multihop. Get the first hop only.
|
|
39
|
+
transfers = [transfer_path[0] for transfer_path in chunk]
|
|
40
|
+
|
|
41
|
+
grouped_jobs.append({
|
|
42
|
+
'transfers': transfers,
|
|
43
|
+
# Job params are not used by globus transfertool, but are needed for further common fts/globus code
|
|
44
|
+
'job_params': {}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return grouped_jobs
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class GlobusTransferStatusReport(TransferStatusReport):
|
|
51
|
+
|
|
52
|
+
supported_db_fields = [
|
|
53
|
+
'state',
|
|
54
|
+
'external_id',
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
def __init__(self, request_id, external_id, globus_response):
|
|
58
|
+
super().__init__(request_id)
|
|
59
|
+
|
|
60
|
+
if globus_response == 'FAILED':
|
|
61
|
+
new_state = RequestState.FAILED
|
|
62
|
+
elif globus_response == 'SUCCEEDED':
|
|
63
|
+
new_state = RequestState.DONE
|
|
64
|
+
else:
|
|
65
|
+
new_state = RequestState.SUBMITTED
|
|
66
|
+
|
|
67
|
+
self.state = new_state
|
|
68
|
+
self.external_id = None
|
|
69
|
+
if new_state in [RequestState.FAILED, RequestState.DONE]:
|
|
70
|
+
self.external_id = external_id
|
|
71
|
+
|
|
72
|
+
def initialize(self, session, logger=logging.log):
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
def get_monitor_msg_fields(self, session, logger=logging.log):
|
|
76
|
+
return {'protocol': 'globus'}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class GlobusTransferTool(Transfertool):
|
|
80
|
+
"""
|
|
81
|
+
Globus implementation of Transfertool abstract base class
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
external_name = 'globus'
|
|
85
|
+
required_rse_attrs = ('globus_endpoint_id', )
|
|
86
|
+
|
|
87
|
+
def __init__(self, external_host, logger=logging.log, group_bulk=200, group_policy='single'):
|
|
88
|
+
"""
|
|
89
|
+
Initializes the transfertool
|
|
90
|
+
|
|
91
|
+
:param external_host: The external host where the transfertool API is running
|
|
92
|
+
"""
|
|
93
|
+
if not external_host:
|
|
94
|
+
external_host = 'Globus Online Transfertool'
|
|
95
|
+
super().__init__(external_host, logger)
|
|
96
|
+
self.group_bulk = group_bulk
|
|
97
|
+
self.group_policy = group_policy
|
|
98
|
+
# TODO: initialize vars from config file here
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def submission_builder_for_path(cls, transfer_path, logger=logging.log):
|
|
102
|
+
hop = transfer_path[0]
|
|
103
|
+
if not cls.can_perform_transfer(hop.src.rse, hop.dst.rse):
|
|
104
|
+
logger(logging.WARNING, "Source or destination globus_endpoint_id not set. Skipping {}".format(hop))
|
|
105
|
+
return [], None
|
|
106
|
+
|
|
107
|
+
return [hop], TransferToolBuilder(cls, external_host='Globus Online Transfertool')
|
|
108
|
+
|
|
109
|
+
def group_into_submit_jobs(self, transfer_paths):
|
|
110
|
+
jobs = bulk_group_transfers(transfer_paths, policy=self.group_policy, group_bulk=self.group_bulk)
|
|
111
|
+
return jobs
|
|
112
|
+
|
|
113
|
+
def submit_one(self, files, timeout=None):
|
|
114
|
+
"""
|
|
115
|
+
Submit transfers to globus API
|
|
116
|
+
|
|
117
|
+
:param files: List of dictionaries describing the file transfers.
|
|
118
|
+
:param job_params: Dictionary containing key/value pairs, for all transfers.
|
|
119
|
+
:param timeout: Timeout in seconds.
|
|
120
|
+
:returns: Globus transfer identifier.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
source_path = files[0]['sources'][0]
|
|
124
|
+
self.logger(logging.INFO, 'source_path: %s' % source_path)
|
|
125
|
+
|
|
126
|
+
source_endpoint_id = files[0]['metadata']['source_globus_endpoint_id']
|
|
127
|
+
|
|
128
|
+
# TODO: use prefix from rse_protocol to properly construct destination url
|
|
129
|
+
# parse and assemble dest_path for Globus endpoint
|
|
130
|
+
dest_path = files[0]['destinations'][0]
|
|
131
|
+
self.logger(logging.INFO, 'dest_path: %s' % dest_path)
|
|
132
|
+
|
|
133
|
+
# TODO: rucio.common.utils.construct_url logic adds unnecessary '/other' into file path
|
|
134
|
+
# s = dest_path.split('/') # s.remove('other') # dest_path = '/'.join(s)
|
|
135
|
+
|
|
136
|
+
destination_endpoint_id = files[0]['metadata']['dest_globus_endpoint_id']
|
|
137
|
+
job_label = files[0]['metadata']['request_id']
|
|
138
|
+
|
|
139
|
+
task_id = submit_xfer(source_endpoint_id, destination_endpoint_id, source_path, dest_path, job_label, recursive=False, logger=self.logger)
|
|
140
|
+
|
|
141
|
+
return task_id
|
|
142
|
+
|
|
143
|
+
def submit(self, transfers, job_params, timeout=None):
|
|
144
|
+
"""
|
|
145
|
+
Submit a bulk transfer to globus API
|
|
146
|
+
|
|
147
|
+
:param transfers: List of dictionaries describing the file transfers.
|
|
148
|
+
:param job_params: Not used by Globus Transfsertool
|
|
149
|
+
:param timeout: Timeout in seconds.
|
|
150
|
+
:returns: Globus transfer identifier.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
# TODO: support passing a recursive parameter to Globus
|
|
154
|
+
submitjob = [
|
|
155
|
+
{
|
|
156
|
+
# Some dict elements are not needed by globus transfertool, but are accessed by further common fts/globus code
|
|
157
|
+
'sources': [s[1] for s in transfer.legacy_sources],
|
|
158
|
+
'destinations': [transfer.dest_url],
|
|
159
|
+
'metadata': {
|
|
160
|
+
'src_rse': transfer.src.rse.name,
|
|
161
|
+
'dst_rse': transfer.dst.rse.name,
|
|
162
|
+
'scope': str(transfer.rws.scope),
|
|
163
|
+
'name': transfer.rws.name,
|
|
164
|
+
'source_globus_endpoint_id': transfer.src.rse.attributes['globus_endpoint_id'],
|
|
165
|
+
'dest_globus_endpoint_id': transfer.dst.rse.attributes['globus_endpoint_id'],
|
|
166
|
+
'filesize': transfer.rws.byte_count,
|
|
167
|
+
},
|
|
168
|
+
}
|
|
169
|
+
for transfer in transfers
|
|
170
|
+
]
|
|
171
|
+
self.logger(logging.DEBUG, '... Starting globus xfer ...')
|
|
172
|
+
self.logger(logging.DEBUG, 'job_files: %s' % submitjob)
|
|
173
|
+
task_id = bulk_submit_xfer(submitjob, recursive=False, logger=self.logger)
|
|
174
|
+
|
|
175
|
+
return task_id
|
|
176
|
+
|
|
177
|
+
def bulk_query(self, requests_by_eid, timeout=None):
|
|
178
|
+
"""
|
|
179
|
+
Query the status of a bulk of transfers in globus API
|
|
180
|
+
|
|
181
|
+
:param requests_by_eid: dictionary {external_id1: {request_id1: request1, ...}, ...}
|
|
182
|
+
:returns: Transfer status information as a dictionary.
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
job_responses = bulk_check_xfers(requests_by_eid, logger=self.logger)
|
|
186
|
+
|
|
187
|
+
response = {}
|
|
188
|
+
for transfer_id, requests in requests_by_eid.items():
|
|
189
|
+
for request_id in requests:
|
|
190
|
+
response.setdefault(transfer_id, {})[request_id] = GlobusTransferStatusReport(request_id, transfer_id, job_responses[transfer_id])
|
|
191
|
+
return response
|
|
192
|
+
|
|
193
|
+
def bulk_update(self, resps, request_ids):
|
|
194
|
+
pass
|
|
195
|
+
|
|
196
|
+
def cancel(self):
|
|
197
|
+
pass
|
|
198
|
+
|
|
199
|
+
def update_priority(self):
|
|
200
|
+
pass
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import datetime
|
|
17
|
+
import logging
|
|
18
|
+
import os
|
|
19
|
+
|
|
20
|
+
from rucio.common.config import config_get, config_get_int, get_config_dirs
|
|
21
|
+
from rucio.common.extra import import_extras
|
|
22
|
+
from rucio.core.monitor import MetricManager
|
|
23
|
+
|
|
24
|
+
EXTRA_MODULES = import_extras(['globus_sdk'])
|
|
25
|
+
|
|
26
|
+
if EXTRA_MODULES['globus_sdk']:
|
|
27
|
+
from globus_sdk import NativeAppAuthClient, RefreshTokenAuthorizer, TransferClient, TransferData, DeleteData # pylint: disable=import-error
|
|
28
|
+
import yaml # pylint: disable=import-error
|
|
29
|
+
|
|
30
|
+
METRICS = MetricManager(module=__name__)
|
|
31
|
+
|
|
32
|
+
GLOBUS_AUTH_APP = config_get('conveyor', 'globus_auth_app', False, None)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def load_config(cfg_file='globus-config.yml', logger=logging.log):
|
|
36
|
+
config = None
|
|
37
|
+
config_dir = get_config_dirs()[0]
|
|
38
|
+
if os.path.isfile(os.path.join(config_dir, cfg_file)):
|
|
39
|
+
config = os.path.join(config_dir, cfg_file)
|
|
40
|
+
else:
|
|
41
|
+
logger(logging.ERROR, 'Could not find globus config file')
|
|
42
|
+
raise Exception
|
|
43
|
+
return yaml.safe_load(open(config).read())
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_transfer_client(logger=logging.log):
|
|
47
|
+
cfg = load_config(logger=logger)
|
|
48
|
+
# cfg = yaml.safe_load(open("/opt/rucio/lib/rucio/transfertool/config.yml"))
|
|
49
|
+
client_id = cfg['globus']['apps'][GLOBUS_AUTH_APP]['client_id']
|
|
50
|
+
auth_client = NativeAppAuthClient(client_id)
|
|
51
|
+
refresh_token = cfg['globus']['apps'][GLOBUS_AUTH_APP]['refresh_token']
|
|
52
|
+
logger(logging.INFO, 'authorizing token...')
|
|
53
|
+
authorizer = RefreshTokenAuthorizer(refresh_token=refresh_token, auth_client=auth_client)
|
|
54
|
+
logger(logging.INFO, 'initializing TransferClient...')
|
|
55
|
+
tc = TransferClient(authorizer=authorizer)
|
|
56
|
+
return tc
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def auto_activate_endpoint(tc, ep_id, logger=logging.log):
|
|
60
|
+
r = tc.endpoint_autoactivate(ep_id, if_expires_in=3600)
|
|
61
|
+
if r['code'] == 'AutoActivationFailed':
|
|
62
|
+
logger(logging.CRITICAL, 'Endpoint({}) Not Active! Error! Source message: {}'.format(ep_id, r['message']))
|
|
63
|
+
# sys.exit(1) # TODO: don't want to exit; hook into graceful exit
|
|
64
|
+
elif r['code'] == 'AutoActivated.CachedCredential':
|
|
65
|
+
logger(logging.INFO, 'Endpoint({}) autoactivated using a cached credential.'.format(ep_id))
|
|
66
|
+
elif r['code'] == 'AutoActivated.GlobusOnlineCredential':
|
|
67
|
+
logger(logging.INFO, ('Endpoint({}) autoactivated using a built-in Globus credential.').format(ep_id))
|
|
68
|
+
elif r['code'] == 'AlreadyActivated':
|
|
69
|
+
logger(logging.INFO, 'Endpoint({}) already active until at least {}'.format(ep_id, 3600))
|
|
70
|
+
return r['code']
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def submit_xfer(source_endpoint_id, destination_endpoint_id, source_path, dest_path, job_label, recursive=False, logger=logging.log):
|
|
74
|
+
tc = get_transfer_client(logger=logger)
|
|
75
|
+
# as both endpoints are expected to be Globus Server endpoints, send auto-activate commands for both globus endpoints
|
|
76
|
+
auto_activate_endpoint(tc, source_endpoint_id, logger=logger)
|
|
77
|
+
auto_activate_endpoint(tc, destination_endpoint_id, logger=logger)
|
|
78
|
+
|
|
79
|
+
# from Globus... sync_level=checksum means that before files are transferred, Globus will compute checksums on the source and
|
|
80
|
+
# destination files, and only transfer files that have different checksums are transferred. verify_checksum=True means that after
|
|
81
|
+
# a file is transferred, Globus will compute checksums on the source and destination files to verify that the file was transferred
|
|
82
|
+
# correctly. If the checksums do not match, it will redo the transfer of that file.
|
|
83
|
+
# tdata = TransferData(tc, source_endpoint_id, destination_endpoint_id, label=job_label, sync_level="checksum", verify_checksum=True)
|
|
84
|
+
tdata = TransferData(tc, source_endpoint_id, destination_endpoint_id, label=job_label,
|
|
85
|
+
sync_level="checksum", notify_on_succeeded=False, notify_on_failed=False)
|
|
86
|
+
tdata.add_item(source_path, dest_path, recursive=recursive)
|
|
87
|
+
|
|
88
|
+
# logging.info('submitting transfer...')
|
|
89
|
+
transfer_result = tc.submit_transfer(tdata)
|
|
90
|
+
# logging.info("task_id =", transfer_result["task_id"])
|
|
91
|
+
|
|
92
|
+
return transfer_result["task_id"]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def bulk_submit_xfer(submitjob, recursive=False, logger=logging.log):
|
|
96
|
+
cfg = load_config(logger=logger)
|
|
97
|
+
client_id = cfg['globus']['apps'][GLOBUS_AUTH_APP]['client_id']
|
|
98
|
+
auth_client = NativeAppAuthClient(client_id)
|
|
99
|
+
refresh_token = cfg['globus']['apps'][GLOBUS_AUTH_APP]['refresh_token']
|
|
100
|
+
source_endpoint_id = submitjob[0].get('metadata').get('source_globus_endpoint_id')
|
|
101
|
+
destination_endpoint_id = submitjob[0].get('metadata').get('dest_globus_endpoint_id')
|
|
102
|
+
authorizer = RefreshTokenAuthorizer(refresh_token=refresh_token, auth_client=auth_client)
|
|
103
|
+
tc = TransferClient(authorizer=authorizer)
|
|
104
|
+
|
|
105
|
+
# make job_label for task a timestamp
|
|
106
|
+
now = datetime.datetime.utcnow()
|
|
107
|
+
job_label = now.strftime('%Y%m%d%H%M%s')
|
|
108
|
+
|
|
109
|
+
# retrieve globus_task_deadline value to enforce time window to complete transfers
|
|
110
|
+
# default is 2880 minutes or 48 hours
|
|
111
|
+
globus_task_deadline = config_get_int('conveyor', 'globus_task_deadline', False, 2880)
|
|
112
|
+
deadline = now + datetime.timedelta(minutes=globus_task_deadline)
|
|
113
|
+
|
|
114
|
+
# from Globus... sync_level=checksum means that before files are transferred, Globus will compute checksums on the source
|
|
115
|
+
# and destination files, and only transfer files that have different checksums are transferred. verify_checksum=True means
|
|
116
|
+
# that after a file is transferred, Globus will compute checksums on the source and destination files to verify that the
|
|
117
|
+
# file was transferred correctly. If the checksums do not match, it will redo the transfer of that file.
|
|
118
|
+
tdata = TransferData(tc, source_endpoint_id, destination_endpoint_id, label=job_label, sync_level="checksum", deadline=str(deadline))
|
|
119
|
+
|
|
120
|
+
for file in submitjob:
|
|
121
|
+
source_path = file.get('sources')[0]
|
|
122
|
+
dest_path = file.get('destinations')[0]
|
|
123
|
+
filesize = file['metadata']['filesize']
|
|
124
|
+
# TODO: support passing a recursive parameter to Globus
|
|
125
|
+
# md5 = file['metadata']['md5']
|
|
126
|
+
# tdata.add_item(source_path, dest_path, recursive=False, external_checksum=md5)
|
|
127
|
+
tdata.add_item(source_path, dest_path, recursive=False)
|
|
128
|
+
METRICS.counter('submit.filesize').inc(filesize)
|
|
129
|
+
|
|
130
|
+
# logging.info('submitting transfer...')
|
|
131
|
+
transfer_result = tc.submit_transfer(tdata)
|
|
132
|
+
logger(logging.INFO, "transfer_result: %s" % transfer_result)
|
|
133
|
+
|
|
134
|
+
return transfer_result["task_id"]
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def check_xfer(task_id, logger=logging.log):
|
|
138
|
+
tc = get_transfer_client(logger=logger)
|
|
139
|
+
transfer = tc.get_task(task_id)
|
|
140
|
+
status = str(transfer["status"])
|
|
141
|
+
return status
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def bulk_check_xfers(task_ids, logger=logging.log):
|
|
145
|
+
tc = get_transfer_client(logger=logger)
|
|
146
|
+
|
|
147
|
+
logger(logging.DEBUG, 'task_ids: %s' % task_ids)
|
|
148
|
+
|
|
149
|
+
responses = {}
|
|
150
|
+
|
|
151
|
+
for task_id in task_ids:
|
|
152
|
+
transfer = tc.get_task(str(task_id))
|
|
153
|
+
logger(logging.DEBUG, 'transfer: %s' % transfer)
|
|
154
|
+
status = str(transfer["status"])
|
|
155
|
+
if status == 'SUCCEEDED':
|
|
156
|
+
METRICS.counter('bytes_transferred').inc(transfer['bytes_transferred'])
|
|
157
|
+
METRICS.counter('effective_bytes_per_second').inc(transfer['effective_bytes_per_second'])
|
|
158
|
+
responses[str(task_id)] = status
|
|
159
|
+
|
|
160
|
+
logger(logging.DEBUG, 'responses: %s' % responses)
|
|
161
|
+
|
|
162
|
+
return responses
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def send_delete_task(endpoint_id=None, path=None, logger=logging.log):
|
|
166
|
+
tc = get_transfer_client(logger=logger)
|
|
167
|
+
ddata = DeleteData(tc, endpoint_id, recursive=True)
|
|
168
|
+
ddata.add_item(path)
|
|
169
|
+
delete_result = tc.submit_delete(ddata)
|
|
170
|
+
|
|
171
|
+
return delete_result
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def send_bulk_delete_task(endpoint_id=None, pfns=None, logger=logging.log):
|
|
175
|
+
tc = get_transfer_client(logger=logger)
|
|
176
|
+
ddata = DeleteData(tc, endpoint_id, recursive=True)
|
|
177
|
+
for pfn in pfns:
|
|
178
|
+
logger(logging.DEBUG, 'pfn: %s' % pfn)
|
|
179
|
+
ddata.add_item(pfn)
|
|
180
|
+
bulk_delete_result = tc.submit_delete(ddata)
|
|
181
|
+
|
|
182
|
+
return bulk_delete_result
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import itertools
|
|
17
|
+
import logging
|
|
18
|
+
import uuid
|
|
19
|
+
from typing import TYPE_CHECKING, Any, Optional, Sequence
|
|
20
|
+
|
|
21
|
+
from rucio.db.sqla.constants import RequestState
|
|
22
|
+
from rucio.transfertool.transfertool import Transfertool, TransferToolBuilder, TransferStatusReport
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from rucio.db.sqla.session import Session
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class MockTransferStatusReport(TransferStatusReport):
|
|
29
|
+
|
|
30
|
+
supported_db_fields = [
|
|
31
|
+
'state',
|
|
32
|
+
'external_id'
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
def __init__(self, request_id: str, external_id: str):
|
|
36
|
+
super().__init__(request_id)
|
|
37
|
+
self.state = RequestState.DONE
|
|
38
|
+
self.external_id = external_id
|
|
39
|
+
|
|
40
|
+
def initialize(self, session: "Session", logger=logging.log):
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
def get_monitor_msg_fields(self, session: "Session", logger=logging.log):
|
|
44
|
+
return {}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class MockTransfertool(Transfertool):
|
|
48
|
+
"""
|
|
49
|
+
Mock implementation of a Rucio transfertool
|
|
50
|
+
|
|
51
|
+
This is not actually used anywhere at the moment
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
external_name = 'mock'
|
|
55
|
+
required_rse_attrs = ()
|
|
56
|
+
|
|
57
|
+
def __init__(self, external_host: str, logger=logging.log):
|
|
58
|
+
super(MockTransfertool, self).__init__(external_host, logger)
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def submission_builder_for_path(cls, transfer_path, logger=logging.log):
|
|
62
|
+
return transfer_path, TransferToolBuilder(cls, external_host='Mock Transfertool')
|
|
63
|
+
|
|
64
|
+
def group_into_submit_jobs(self, transfers):
|
|
65
|
+
return [{'transfers': list(itertools.chain.from_iterable(transfers)), 'job_params': {}}]
|
|
66
|
+
|
|
67
|
+
def submit(self, files, job_params, timeout=None):
|
|
68
|
+
return str(uuid.uuid1())
|
|
69
|
+
|
|
70
|
+
def bulk_query(self, requests_by_eid: dict[str, dict[str, dict[str, Any]]], timeout: Optional[float] = None):
|
|
71
|
+
response = {}
|
|
72
|
+
for transfer_id, requests in requests_by_eid.items():
|
|
73
|
+
for request_id in requests:
|
|
74
|
+
response.setdefault(transfer_id, {})[request_id] = MockTransferStatusReport(request_id, transfer_id)
|
|
75
|
+
return response
|
|
76
|
+
|
|
77
|
+
def cancel(self, transfer_ids: Sequence[str], timeout: Optional[float] = None):
|
|
78
|
+
return True
|
|
79
|
+
|
|
80
|
+
def update_priority(self, transfer_id: str, priority: int, timeout: Optional[float] = None):
|
|
81
|
+
return True
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from abc import ABCMeta, abstractmethod
|
|
18
|
+
from typing import TYPE_CHECKING
|
|
19
|
+
|
|
20
|
+
from rucio.core.request import get_request
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from rucio.core.rse import RseData
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TransferToolBuilder(object):
|
|
27
|
+
"""
|
|
28
|
+
Builder for Transfertool objects.
|
|
29
|
+
Stores the parameters needed to create the Transfertool object of the given type/class.
|
|
30
|
+
|
|
31
|
+
Implements __hash__ and __eq__ to allow using it as key in dictionaries and group transfers
|
|
32
|
+
by common transfertool.
|
|
33
|
+
"""
|
|
34
|
+
def __init__(self, transfertool_class, **kwargs):
|
|
35
|
+
self.transfertool_class = transfertool_class
|
|
36
|
+
self.fixed_kwargs = frozenset(kwargs.items())
|
|
37
|
+
|
|
38
|
+
def __str__(self):
|
|
39
|
+
return self.transfertool_class.__name__
|
|
40
|
+
|
|
41
|
+
def __hash__(self):
|
|
42
|
+
return hash(frozenset(self.__dict__.items()))
|
|
43
|
+
|
|
44
|
+
def __eq__(self, other):
|
|
45
|
+
return self.__class__ == other.__class__ and self.__dict__ == other.__dict__
|
|
46
|
+
|
|
47
|
+
def make_transfertool(self, **additional_kwargs):
|
|
48
|
+
all_kwargs = dict(self.fixed_kwargs)
|
|
49
|
+
all_kwargs.update(additional_kwargs)
|
|
50
|
+
return self.transfertool_class(**all_kwargs)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class TransferStatusReport(object, metaclass=ABCMeta):
|
|
54
|
+
"""
|
|
55
|
+
Allows to compute the changes which have to be applied to the database
|
|
56
|
+
to reflect the current status reported by the external transfertool into
|
|
57
|
+
the database.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
supported_db_fields = [
|
|
61
|
+
'state',
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
def __init__(self, request_id, request=None):
|
|
65
|
+
self.request_id = request_id
|
|
66
|
+
self.__request = request # Optional: DB request. If provided, saves us a database call to fetch it by request_id
|
|
67
|
+
self.__initialized = False
|
|
68
|
+
|
|
69
|
+
# Supported db fields bellow
|
|
70
|
+
self.state = None
|
|
71
|
+
|
|
72
|
+
@abstractmethod
|
|
73
|
+
def initialize(self, session, logger=logging.log):
|
|
74
|
+
"""
|
|
75
|
+
Initialize all fields from self.supported_update_fields
|
|
76
|
+
"""
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
@abstractmethod
|
|
80
|
+
def get_monitor_msg_fields(self, session, logger=logging.log):
|
|
81
|
+
"""
|
|
82
|
+
Return the fields which will be included in the message sent to hermes.
|
|
83
|
+
"""
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
def ensure_initialized(self, session, logger=logging.log):
|
|
87
|
+
if not self.__initialized:
|
|
88
|
+
self.initialize(session, logger)
|
|
89
|
+
self.__initialized = True
|
|
90
|
+
|
|
91
|
+
def request(self, session):
|
|
92
|
+
"""
|
|
93
|
+
Fetch the request by request_id if needed.
|
|
94
|
+
"""
|
|
95
|
+
if not self.__request:
|
|
96
|
+
self.__request = get_request(self.request_id, session=session)
|
|
97
|
+
return self.__request
|
|
98
|
+
|
|
99
|
+
def get_db_fields_to_update(self, session, logger=logging.log):
|
|
100
|
+
"""
|
|
101
|
+
Returns the fields which have to be updated in the request
|
|
102
|
+
"""
|
|
103
|
+
self.ensure_initialized(session, logger)
|
|
104
|
+
|
|
105
|
+
updates = {}
|
|
106
|
+
for field in self.supported_db_fields:
|
|
107
|
+
field_value = getattr(self, field)
|
|
108
|
+
if field_value:
|
|
109
|
+
updates[field] = field_value
|
|
110
|
+
return updates
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class Transfertool(object, metaclass=ABCMeta):
|
|
114
|
+
"""
|
|
115
|
+
Interface definition of the Rucio transfertool
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
external_name = ''
|
|
119
|
+
required_rse_attrs = ('globus_endpoint_id', )
|
|
120
|
+
|
|
121
|
+
def __init__(self, external_host, logger=logging.log):
|
|
122
|
+
"""
|
|
123
|
+
Initializes the transfertool
|
|
124
|
+
|
|
125
|
+
:param external_host: The external host where the transfertool API is running
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
self.external_host = external_host
|
|
129
|
+
self.logger = logger
|
|
130
|
+
|
|
131
|
+
def __str__(self):
|
|
132
|
+
return self.external_host if self.external_host is not None else self.__class__.__name__
|
|
133
|
+
|
|
134
|
+
@classmethod
|
|
135
|
+
def can_perform_transfer(cls, source_rse: "RseData", dest_rse: "RseData"):
|
|
136
|
+
"""
|
|
137
|
+
Return True if this transfertool is able to perform a transfer between the given source and destination rses
|
|
138
|
+
"""
|
|
139
|
+
if (
|
|
140
|
+
all(source_rse.attributes.get(attribute) is not None for attribute in cls.required_rse_attrs)
|
|
141
|
+
and all(dest_rse.attributes.get(attribute) is not None for attribute in cls.required_rse_attrs)
|
|
142
|
+
):
|
|
143
|
+
return True
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
@classmethod
|
|
147
|
+
def submission_builder_for_path(cls, transfer_path, logger=logging.log):
|
|
148
|
+
"""
|
|
149
|
+
Analyze the transfer path. If this transfertool class can submit the given transfers, return
|
|
150
|
+
a TransferToolBuilder instance capable to build transfertool objects configured for this
|
|
151
|
+
particular submission.
|
|
152
|
+
:param transfer_path: List of DirectTransferDefinitions
|
|
153
|
+
:param logger: logger instance
|
|
154
|
+
:return: a tuple: a sub-path starting at the first node from transfer_path, and a TransfertoolBuilder instance
|
|
155
|
+
capable to submit this sub-path. Returns ([], None) if submission is impossible.
|
|
156
|
+
"""
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
@abstractmethod
|
|
160
|
+
def group_into_submit_jobs(self, transfer_paths):
|
|
161
|
+
"""
|
|
162
|
+
Takes an iterable over transfer paths, and create groups which can be submitted in one call to submit()
|
|
163
|
+
|
|
164
|
+
:param transfer_paths: Iterable over (potentially multihop) transfer paths.
|
|
165
|
+
:return: list of dicts of the form {"transfers": <transfer list>, "job_params": <data blob>}
|
|
166
|
+
"""
|
|
167
|
+
pass
|
|
168
|
+
|
|
169
|
+
@abstractmethod
|
|
170
|
+
def submit(self, transfers, job_params, timeout=None):
|
|
171
|
+
"""
|
|
172
|
+
Submit transfers to the transfertool.
|
|
173
|
+
|
|
174
|
+
:param transfers: List of dictionaries describing the file transfers.
|
|
175
|
+
:param job_params: Dictionary containing key/value pairs, for all transfers.
|
|
176
|
+
:param timeout: Timeout in seconds.
|
|
177
|
+
:returns: Transfertool internal identifiers.
|
|
178
|
+
"""
|
|
179
|
+
pass
|
|
180
|
+
|
|
181
|
+
@abstractmethod
|
|
182
|
+
def bulk_query(self, requests_by_eid, timeout=None) -> dict[str, dict[str, TransferStatusReport]]:
|
|
183
|
+
"""
|
|
184
|
+
Query the status of a bulk of transfers in FTS3 via JSON.
|
|
185
|
+
|
|
186
|
+
:param requests_by_eid: dictionary {external_id1: {request_id1: request1, ...}, ...} of request to be queried
|
|
187
|
+
:returns: Transfer status information as a dictionary.
|
|
188
|
+
"""
|
|
189
|
+
pass
|
|
190
|
+
|
|
191
|
+
@abstractmethod
|
|
192
|
+
def cancel(self, transfer_ids, timeout=None):
|
|
193
|
+
"""
|
|
194
|
+
Cancel transfers that have been submitted to the transfertool.
|
|
195
|
+
|
|
196
|
+
:param transfer_ids: Transfertool internal transfer identifiers as list of strings.
|
|
197
|
+
:param timeout: Timeout in seconds.
|
|
198
|
+
:returns: True if cancellation was successful.
|
|
199
|
+
"""
|
|
200
|
+
pass
|
|
201
|
+
|
|
202
|
+
@abstractmethod
|
|
203
|
+
def update_priority(self, transfer_id, priority, timeout=None):
|
|
204
|
+
"""
|
|
205
|
+
Update the priority of a transfer that has been submitted to the transfertool.
|
|
206
|
+
|
|
207
|
+
:param transfer_id: Transfertool internal transfer identifier as a string.
|
|
208
|
+
:param priority: Job priority as an integer from 1 to 5.
|
|
209
|
+
:param timeout: Timeout in seconds.
|
|
210
|
+
:returns: True if update was successful.
|
|
211
|
+
"""
|
|
212
|
+
pass
|
rucio/vcsversion.py
ADDED