rucio 32.8.6__py3-none-any.whl → 35.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/__init__.py +0 -1
- rucio/alembicrevision.py +1 -2
- rucio/client/__init__.py +0 -1
- rucio/client/accountclient.py +45 -25
- rucio/client/accountlimitclient.py +37 -9
- rucio/client/baseclient.py +199 -154
- rucio/client/client.py +2 -3
- rucio/client/configclient.py +19 -6
- rucio/client/credentialclient.py +9 -4
- rucio/client/didclient.py +238 -63
- rucio/client/diracclient.py +13 -5
- rucio/client/downloadclient.py +162 -51
- rucio/client/exportclient.py +4 -4
- rucio/client/fileclient.py +3 -4
- rucio/client/importclient.py +4 -4
- rucio/client/lifetimeclient.py +21 -5
- rucio/client/lockclient.py +18 -8
- rucio/client/{metaclient.py → metaconventionsclient.py} +18 -15
- rucio/client/pingclient.py +0 -1
- rucio/client/replicaclient.py +15 -5
- rucio/client/requestclient.py +35 -19
- rucio/client/rseclient.py +133 -51
- rucio/client/ruleclient.py +29 -22
- rucio/client/scopeclient.py +8 -6
- rucio/client/subscriptionclient.py +47 -35
- rucio/client/touchclient.py +8 -4
- rucio/client/uploadclient.py +166 -82
- rucio/common/__init__.py +0 -1
- rucio/common/cache.py +4 -4
- rucio/common/config.py +52 -47
- rucio/common/constants.py +69 -2
- rucio/common/constraints.py +0 -1
- rucio/common/didtype.py +24 -22
- rucio/common/dumper/__init__.py +70 -41
- rucio/common/dumper/consistency.py +26 -22
- rucio/common/dumper/data_models.py +16 -23
- rucio/common/dumper/path_parsing.py +0 -1
- rucio/common/exception.py +281 -222
- rucio/common/extra.py +0 -1
- rucio/common/logging.py +54 -38
- rucio/common/pcache.py +122 -101
- rucio/common/plugins.py +153 -0
- rucio/common/policy.py +4 -4
- rucio/common/schema/__init__.py +17 -10
- rucio/common/schema/atlas.py +7 -5
- rucio/common/schema/belleii.py +7 -5
- rucio/common/schema/domatpc.py +7 -5
- rucio/common/schema/escape.py +7 -5
- rucio/common/schema/generic.py +8 -6
- rucio/common/schema/generic_multi_vo.py +7 -5
- rucio/common/schema/icecube.py +7 -5
- rucio/common/stomp_utils.py +0 -1
- rucio/common/stopwatch.py +0 -1
- rucio/common/test_rucio_server.py +2 -2
- rucio/common/types.py +262 -17
- rucio/common/utils.py +743 -451
- rucio/core/__init__.py +0 -1
- rucio/core/account.py +99 -29
- rucio/core/account_counter.py +89 -24
- rucio/core/account_limit.py +90 -24
- rucio/core/authentication.py +86 -29
- rucio/core/config.py +108 -38
- rucio/core/credential.py +14 -7
- rucio/core/did.py +680 -782
- rucio/core/did_meta_plugins/__init__.py +8 -6
- rucio/core/did_meta_plugins/did_column_meta.py +17 -12
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +60 -11
- rucio/core/did_meta_plugins/filter_engine.py +90 -50
- rucio/core/did_meta_plugins/json_meta.py +41 -16
- rucio/core/did_meta_plugins/mongo_meta.py +25 -8
- rucio/core/did_meta_plugins/postgres_meta.py +3 -4
- rucio/core/dirac.py +46 -17
- rucio/core/distance.py +66 -43
- rucio/core/exporter.py +5 -5
- rucio/core/heartbeat.py +181 -81
- rucio/core/identity.py +22 -12
- rucio/core/importer.py +23 -12
- rucio/core/lifetime_exception.py +32 -32
- rucio/core/lock.py +244 -142
- rucio/core/message.py +79 -38
- rucio/core/{meta.py → meta_conventions.py} +57 -44
- rucio/core/monitor.py +19 -13
- rucio/core/naming_convention.py +68 -27
- rucio/core/nongrid_trace.py +17 -5
- rucio/core/oidc.py +151 -29
- rucio/core/permission/__init__.py +18 -6
- rucio/core/permission/atlas.py +50 -35
- rucio/core/permission/belleii.py +6 -5
- rucio/core/permission/escape.py +8 -6
- rucio/core/permission/generic.py +82 -80
- rucio/core/permission/generic_multi_vo.py +9 -7
- rucio/core/quarantined_replica.py +91 -58
- rucio/core/replica.py +1303 -772
- rucio/core/replica_sorter.py +10 -12
- rucio/core/request.py +1133 -285
- rucio/core/rse.py +142 -102
- rucio/core/rse_counter.py +49 -18
- rucio/core/rse_expression_parser.py +6 -7
- rucio/core/rse_selector.py +41 -16
- rucio/core/rule.py +1538 -474
- rucio/core/rule_grouping.py +213 -68
- rucio/core/scope.py +50 -22
- rucio/core/subscription.py +92 -44
- rucio/core/topology.py +66 -24
- rucio/core/trace.py +42 -28
- rucio/core/transfer.py +543 -259
- rucio/core/vo.py +36 -18
- rucio/core/volatile_replica.py +59 -32
- rucio/daemons/__init__.py +0 -1
- rucio/daemons/abacus/__init__.py +0 -1
- rucio/daemons/abacus/account.py +29 -19
- rucio/daemons/abacus/collection_replica.py +21 -10
- rucio/daemons/abacus/rse.py +22 -12
- rucio/daemons/atropos/__init__.py +0 -1
- rucio/daemons/atropos/atropos.py +1 -2
- rucio/daemons/auditor/__init__.py +56 -28
- rucio/daemons/auditor/hdfs.py +17 -6
- rucio/daemons/auditor/srmdumps.py +116 -45
- rucio/daemons/automatix/__init__.py +0 -1
- rucio/daemons/automatix/automatix.py +30 -18
- rucio/daemons/badreplicas/__init__.py +0 -1
- rucio/daemons/badreplicas/minos.py +29 -18
- rucio/daemons/badreplicas/minos_temporary_expiration.py +5 -7
- rucio/daemons/badreplicas/necromancer.py +9 -13
- rucio/daemons/bb8/__init__.py +0 -1
- rucio/daemons/bb8/bb8.py +10 -13
- rucio/daemons/bb8/common.py +151 -154
- rucio/daemons/bb8/nuclei_background_rebalance.py +15 -9
- rucio/daemons/bb8/t2_background_rebalance.py +15 -8
- rucio/daemons/c3po/__init__.py +0 -1
- rucio/daemons/c3po/algorithms/__init__.py +0 -1
- rucio/daemons/c3po/algorithms/simple.py +8 -5
- rucio/daemons/c3po/algorithms/t2_free_space.py +10 -7
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +10 -7
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +30 -15
- rucio/daemons/c3po/c3po.py +81 -52
- rucio/daemons/c3po/collectors/__init__.py +0 -1
- rucio/daemons/c3po/collectors/agis.py +17 -17
- rucio/daemons/c3po/collectors/free_space.py +32 -13
- rucio/daemons/c3po/collectors/jedi_did.py +14 -5
- rucio/daemons/c3po/collectors/mock_did.py +11 -6
- rucio/daemons/c3po/collectors/network_metrics.py +12 -4
- rucio/daemons/c3po/collectors/workload.py +21 -19
- rucio/daemons/c3po/utils/__init__.py +0 -1
- rucio/daemons/c3po/utils/dataset_cache.py +15 -5
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +16 -5
- rucio/daemons/c3po/utils/expiring_list.py +6 -7
- rucio/daemons/c3po/utils/popularity.py +5 -2
- rucio/daemons/c3po/utils/timeseries.py +25 -12
- rucio/daemons/cache/__init__.py +0 -1
- rucio/daemons/cache/consumer.py +21 -15
- rucio/daemons/common.py +42 -18
- rucio/daemons/conveyor/__init__.py +0 -1
- rucio/daemons/conveyor/common.py +69 -37
- rucio/daemons/conveyor/finisher.py +83 -46
- rucio/daemons/conveyor/poller.py +101 -69
- rucio/daemons/conveyor/preparer.py +35 -28
- rucio/daemons/conveyor/receiver.py +64 -21
- rucio/daemons/conveyor/stager.py +33 -28
- rucio/daemons/conveyor/submitter.py +71 -47
- rucio/daemons/conveyor/throttler.py +99 -35
- rucio/daemons/follower/__init__.py +0 -1
- rucio/daemons/follower/follower.py +12 -8
- rucio/daemons/hermes/__init__.py +0 -1
- rucio/daemons/hermes/hermes.py +57 -21
- rucio/daemons/judge/__init__.py +0 -1
- rucio/daemons/judge/cleaner.py +27 -17
- rucio/daemons/judge/evaluator.py +31 -18
- rucio/daemons/judge/injector.py +31 -23
- rucio/daemons/judge/repairer.py +28 -18
- rucio/daemons/oauthmanager/__init__.py +0 -1
- rucio/daemons/oauthmanager/oauthmanager.py +7 -8
- rucio/daemons/reaper/__init__.py +0 -1
- rucio/daemons/reaper/dark_reaper.py +15 -9
- rucio/daemons/reaper/reaper.py +109 -67
- rucio/daemons/replicarecoverer/__init__.py +0 -1
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +255 -116
- rucio/{api → daemons/rsedecommissioner}/__init__.py +0 -1
- 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 +451 -0
- rucio/daemons/rsedecommissioner/profiles/types.py +92 -0
- rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
- rucio/daemons/storage/__init__.py +0 -1
- rucio/daemons/storage/consistency/__init__.py +0 -1
- rucio/daemons/storage/consistency/actions.py +152 -59
- rucio/daemons/tracer/__init__.py +0 -1
- rucio/daemons/tracer/kronos.py +47 -24
- rucio/daemons/transmogrifier/__init__.py +0 -1
- rucio/daemons/transmogrifier/transmogrifier.py +35 -26
- rucio/daemons/undertaker/__init__.py +0 -1
- rucio/daemons/undertaker/undertaker.py +10 -10
- rucio/db/__init__.py +0 -1
- rucio/db/sqla/__init__.py +16 -2
- rucio/db/sqla/constants.py +10 -1
- rucio/db/sqla/migrate_repo/__init__.py +0 -1
- rucio/db/sqla/migrate_repo/env.py +0 -1
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +0 -1
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +1 -3
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +0 -3
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +1 -4
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +0 -1
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +0 -2
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +0 -2
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +0 -3
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +0 -1
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +1 -2
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +0 -1
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +0 -3
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +1 -4
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +0 -2
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +0 -3
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +1 -2
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +0 -1
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +0 -1
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +0 -2
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +0 -2
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +1 -4
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +1 -4
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +0 -1
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +1 -3
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +0 -2
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +1 -3
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +1 -2
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +1 -3
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +0 -2
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +2 -3
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +1 -4
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +0 -1
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +0 -1
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +0 -1
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +0 -2
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +0 -3
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +0 -2
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +2 -4
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +0 -2
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +1 -4
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +0 -2
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +0 -3
- 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 +0 -2
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +0 -2
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +0 -3
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +0 -3
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +1 -3
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +1 -3
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +0 -3
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +1 -2
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +2 -4
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +0 -1
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +1 -4
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +0 -2
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +1 -2
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +0 -3
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +1 -3
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +0 -3
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +0 -1
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +0 -2
- 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 +1 -3
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +0 -2
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +1 -4
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +0 -1
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +0 -1
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +1 -4
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +0 -1
- 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 +0 -3
- 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 +1 -2
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +1 -3
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +1 -5
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +1 -3
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +0 -3
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +1 -3
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +0 -3
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +1 -4
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +1 -2
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +1 -4
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +1 -3
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +1 -4
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +0 -2
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +1 -3
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +0 -1
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +1 -2
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +1 -3
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +0 -2
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +0 -1
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +1 -2
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +0 -3
- rucio/db/sqla/models.py +122 -216
- rucio/db/sqla/sautils.py +12 -5
- rucio/db/sqla/session.py +71 -43
- rucio/db/sqla/types.py +3 -4
- rucio/db/sqla/util.py +91 -69
- rucio/gateway/__init__.py +13 -0
- rucio/{api → gateway}/account.py +119 -46
- rucio/{api → gateway}/account_limit.py +12 -13
- rucio/{api → gateway}/authentication.py +106 -33
- rucio/{api → gateway}/config.py +12 -13
- rucio/{api → gateway}/credential.py +15 -4
- rucio/{api → gateway}/did.py +384 -140
- rucio/{api → gateway}/dirac.py +16 -6
- rucio/{api → gateway}/exporter.py +3 -4
- rucio/{api → gateway}/heartbeat.py +17 -5
- rucio/{api → gateway}/identity.py +63 -19
- rucio/{api → gateway}/importer.py +3 -4
- rucio/{api → gateway}/lifetime_exception.py +35 -10
- rucio/{api → gateway}/lock.py +34 -12
- rucio/{api/meta.py → gateway/meta_conventions.py} +18 -16
- rucio/{api → gateway}/permission.py +4 -5
- rucio/{api → gateway}/quarantined_replica.py +13 -4
- rucio/{api → gateway}/replica.py +12 -11
- rucio/{api → gateway}/request.py +129 -28
- rucio/{api → gateway}/rse.py +11 -12
- rucio/{api → gateway}/rule.py +117 -35
- rucio/{api → gateway}/scope.py +24 -14
- rucio/{api → gateway}/subscription.py +65 -43
- rucio/{api → gateway}/vo.py +17 -7
- rucio/rse/__init__.py +3 -4
- rucio/rse/protocols/__init__.py +0 -1
- rucio/rse/protocols/bittorrent.py +184 -0
- rucio/rse/protocols/cache.py +1 -2
- rucio/rse/protocols/dummy.py +1 -2
- rucio/rse/protocols/gfal.py +12 -10
- rucio/rse/protocols/globus.py +7 -7
- rucio/rse/protocols/gsiftp.py +2 -3
- rucio/rse/protocols/http_cache.py +1 -2
- rucio/rse/protocols/mock.py +1 -2
- rucio/rse/protocols/ngarc.py +1 -2
- rucio/rse/protocols/posix.py +12 -13
- rucio/rse/protocols/protocol.py +116 -52
- rucio/rse/protocols/rclone.py +6 -7
- rucio/rse/protocols/rfio.py +4 -5
- rucio/rse/protocols/srm.py +9 -10
- rucio/rse/protocols/ssh.py +8 -9
- rucio/rse/protocols/storm.py +2 -3
- rucio/rse/protocols/webdav.py +17 -14
- rucio/rse/protocols/xrootd.py +23 -17
- rucio/rse/rsemanager.py +19 -7
- rucio/tests/__init__.py +0 -1
- rucio/tests/common.py +43 -17
- rucio/tests/common_server.py +3 -3
- rucio/transfertool/__init__.py +0 -1
- rucio/transfertool/bittorrent.py +199 -0
- rucio/transfertool/bittorrent_driver.py +52 -0
- rucio/transfertool/bittorrent_driver_qbittorrent.py +133 -0
- rucio/transfertool/fts3.py +250 -138
- rucio/transfertool/fts3_plugins.py +152 -0
- rucio/transfertool/globus.py +9 -8
- rucio/transfertool/globus_library.py +1 -2
- rucio/transfertool/mock.py +21 -12
- rucio/transfertool/transfertool.py +33 -24
- rucio/vcsversion.py +4 -4
- rucio/version.py +5 -13
- rucio/web/__init__.py +0 -1
- rucio/web/rest/__init__.py +0 -1
- rucio/web/rest/flaskapi/__init__.py +0 -1
- rucio/web/rest/flaskapi/authenticated_bp.py +0 -1
- rucio/web/rest/flaskapi/v1/__init__.py +0 -1
- rucio/web/rest/flaskapi/v1/accountlimits.py +15 -13
- rucio/web/rest/flaskapi/v1/accounts.py +49 -48
- rucio/web/rest/flaskapi/v1/archives.py +12 -10
- rucio/web/rest/flaskapi/v1/auth.py +146 -144
- rucio/web/rest/flaskapi/v1/common.py +82 -41
- rucio/web/rest/flaskapi/v1/config.py +5 -6
- rucio/web/rest/flaskapi/v1/credentials.py +7 -8
- rucio/web/rest/flaskapi/v1/dids.py +158 -28
- rucio/web/rest/flaskapi/v1/dirac.py +8 -8
- rucio/web/rest/flaskapi/v1/export.py +3 -5
- rucio/web/rest/flaskapi/v1/heartbeats.py +3 -5
- rucio/web/rest/flaskapi/v1/identities.py +3 -5
- rucio/web/rest/flaskapi/v1/import.py +3 -4
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +6 -9
- rucio/web/rest/flaskapi/v1/locks.py +2 -4
- rucio/web/rest/flaskapi/v1/main.py +10 -2
- rucio/web/rest/flaskapi/v1/{meta.py → meta_conventions.py} +26 -11
- rucio/web/rest/flaskapi/v1/metrics.py +1 -2
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +4 -4
- rucio/web/rest/flaskapi/v1/ping.py +6 -7
- rucio/web/rest/flaskapi/v1/redirect.py +8 -9
- rucio/web/rest/flaskapi/v1/replicas.py +43 -19
- rucio/web/rest/flaskapi/v1/requests.py +178 -21
- rucio/web/rest/flaskapi/v1/rses.py +61 -26
- rucio/web/rest/flaskapi/v1/rules.py +48 -18
- rucio/web/rest/flaskapi/v1/scopes.py +3 -5
- rucio/web/rest/flaskapi/v1/subscriptions.py +22 -18
- rucio/web/rest/flaskapi/v1/traces.py +4 -4
- rucio/web/rest/flaskapi/v1/types.py +20 -0
- rucio/web/rest/flaskapi/v1/vos.py +3 -5
- rucio/web/rest/main.py +0 -1
- rucio/web/rest/metrics.py +0 -1
- rucio/web/rest/ping.py +27 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/ldap.cfg.template +1 -1
- rucio-35.8.0.data/data/rucio/requirements.server.txt +268 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/bootstrap.py +3 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/merge_rucio_configs.py +2 -5
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/reset_database.py +3 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio +87 -85
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-account +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-collection-replica +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-rse +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-admin +45 -32
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-atropos +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-auditor +13 -7
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-automatix +1 -2
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-bb8 +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-c3po +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-client +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-consumer +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-finisher +1 -2
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-poller +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-preparer +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-receiver +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-stager +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-submitter +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-throttler +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dark-reaper +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dumper +11 -10
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-follower +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-hermes +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-cleaner +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-evaluator +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-injector +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-repairer +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-kronos +1 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos-temporary-expiration +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-necromancer +1 -2
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-oauth-manager +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-reaper +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-replica-recoverer +6 -7
- rucio-35.8.0.data/scripts/rucio-rse-decommissioner +66 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-storage-consistency-actions +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-transmogrifier +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-undertaker +1 -2
- rucio-35.8.0.dist-info/METADATA +72 -0
- rucio-35.8.0.dist-info/RECORD +493 -0
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/WHEEL +1 -1
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/AUTHORS.rst +3 -0
- rucio/api/temporary_did.py +0 -49
- rucio/common/schema/cms.py +0 -478
- rucio/common/schema/lsst.py +0 -423
- rucio/core/permission/cms.py +0 -1166
- rucio/core/temporary_did.py +0 -188
- rucio/daemons/reaper/light_reaper.py +0 -255
- rucio/web/rest/flaskapi/v1/tmp_dids.py +0 -115
- rucio-32.8.6.data/data/rucio/requirements.txt +0 -55
- rucio-32.8.6.data/scripts/rucio-light-reaper +0 -53
- rucio-32.8.6.dist-info/METADATA +0 -83
- rucio-32.8.6.dist-info/RECORD +0 -481
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic.ini.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/LICENSE +0 -0
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/top_level.txt +0 -0
rucio/daemons/conveyor/stager.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -19,8 +18,7 @@ Conveyor stager is a daemon to manage stagein file transfers.
|
|
|
19
18
|
|
|
20
19
|
import logging
|
|
21
20
|
import threading
|
|
22
|
-
from
|
|
23
|
-
from typing import Optional
|
|
21
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
24
22
|
|
|
25
23
|
import rucio.db.sqla.util
|
|
26
24
|
from rucio.common import exception
|
|
@@ -32,22 +30,28 @@ from rucio.daemons.conveyor.submitter import submitter
|
|
|
32
30
|
from rucio.db.sqla.constants import RequestType
|
|
33
31
|
from rucio.transfertool.fts3 import FTS3Transfertool
|
|
34
32
|
|
|
33
|
+
if TYPE_CHECKING:
|
|
34
|
+
from collections.abc import Mapping, Sequence
|
|
35
|
+
from types import FrameType
|
|
36
|
+
|
|
37
|
+
from rucio.common.types import RSESettingsDict
|
|
38
|
+
|
|
35
39
|
METRICS = MetricManager(module=__name__)
|
|
36
40
|
GRACEFUL_STOP = threading.Event()
|
|
37
41
|
DAEMON_NAME = 'conveyor-stager'
|
|
38
42
|
|
|
39
43
|
|
|
40
44
|
def stager(
|
|
41
|
-
once=False,
|
|
42
|
-
rses=None,
|
|
43
|
-
bulk=100,
|
|
44
|
-
group_bulk=1,
|
|
45
|
-
group_policy='rule',
|
|
46
|
-
source_strategy=None,
|
|
47
|
-
activities=None,
|
|
48
|
-
sleep_time=600,
|
|
49
|
-
total_threads=1
|
|
50
|
-
):
|
|
45
|
+
once: bool = False,
|
|
46
|
+
rses: Optional[list["RSESettingsDict"]] = None,
|
|
47
|
+
bulk: int = 100,
|
|
48
|
+
group_bulk: int = 1,
|
|
49
|
+
group_policy: str = 'rule',
|
|
50
|
+
source_strategy: Optional[str] = None,
|
|
51
|
+
activities: Optional[list[str]] = None,
|
|
52
|
+
sleep_time: int = 600,
|
|
53
|
+
total_threads: int = 1
|
|
54
|
+
) -> None:
|
|
51
55
|
|
|
52
56
|
submitter(
|
|
53
57
|
once=once,
|
|
@@ -71,7 +75,7 @@ def stager(
|
|
|
71
75
|
)
|
|
72
76
|
|
|
73
77
|
|
|
74
|
-
def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> None:
|
|
78
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
75
79
|
"""
|
|
76
80
|
Graceful exit.
|
|
77
81
|
"""
|
|
@@ -80,22 +84,23 @@ def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> Non
|
|
|
80
84
|
|
|
81
85
|
|
|
82
86
|
def run(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
):
|
|
87
|
+
once: bool = False,
|
|
88
|
+
total_threads: int = 1,
|
|
89
|
+
group_bulk: int = 1,
|
|
90
|
+
group_policy: str = 'rule',
|
|
91
|
+
rses: Optional["Sequence[Mapping[str, Any]]"] = None,
|
|
92
|
+
include_rses: Optional[str] = None,
|
|
93
|
+
exclude_rses: Optional[str] = None,
|
|
94
|
+
vos: Optional[list[str]] = None,
|
|
95
|
+
bulk: int = 100,
|
|
96
|
+
source_strategy: Optional[str] = None,
|
|
97
|
+
activities: Optional[list[str]] = None,
|
|
98
|
+
sleep_time: int = 600
|
|
99
|
+
) -> None:
|
|
96
100
|
"""
|
|
97
|
-
Starts up the
|
|
101
|
+
Starts up the conveyor threads.
|
|
98
102
|
"""
|
|
103
|
+
activities = activities or []
|
|
99
104
|
setup_logging(process_name=DAEMON_NAME)
|
|
100
105
|
|
|
101
106
|
if rucio.db.sqla.util.is_old_db():
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -19,27 +18,28 @@ Conveyor transfer submitter is a daemon to manage non-tape file transfers.
|
|
|
19
18
|
import logging
|
|
20
19
|
import threading
|
|
21
20
|
from collections.abc import Mapping
|
|
22
|
-
from
|
|
23
|
-
from typing import TYPE_CHECKING, Any, Optional
|
|
21
|
+
from typing import TYPE_CHECKING, Optional
|
|
24
22
|
|
|
25
23
|
import rucio.db.sqla.util
|
|
26
24
|
from rucio.common import exception
|
|
27
|
-
from rucio.common.config import config_get, config_get_bool, config_get_int, config_get_list
|
|
25
|
+
from rucio.common.config import config_get, config_get_bool, config_get_float, config_get_int, config_get_list
|
|
28
26
|
from rucio.common.logging import setup_logging
|
|
29
27
|
from rucio.common.schema import get_schema_value
|
|
30
28
|
from rucio.common.stopwatch import Stopwatch
|
|
31
29
|
from rucio.core.monitor import MetricManager
|
|
32
|
-
from rucio.core.request import list_and_mark_transfer_requests_and_source_replicas
|
|
33
|
-
from rucio.core.topology import
|
|
34
|
-
from rucio.core.transfer import DEFAULT_MULTIHOP_TOMBSTONE_DELAY, list_transfer_admin_accounts, transfer_path_str
|
|
35
|
-
|
|
36
|
-
from rucio.daemons.common import
|
|
37
|
-
from rucio.
|
|
38
|
-
from rucio.db.sqla.constants import RequestType, RequestState
|
|
30
|
+
from rucio.core.request import RequestWithSources, list_and_mark_transfer_requests_and_source_replicas
|
|
31
|
+
from rucio.core.topology import ExpiringObjectCache, Topology
|
|
32
|
+
from rucio.core.transfer import DEFAULT_MULTIHOP_TOMBSTONE_DELAY, TRANSFERTOOL_CLASSES_BY_NAME, ProtocolFactory, list_transfer_admin_accounts, transfer_path_str
|
|
33
|
+
from rucio.daemons.common import ProducerConsumerDaemon, db_workqueue
|
|
34
|
+
from rucio.daemons.conveyor.common import get_conveyor_rses, pick_and_prepare_submission_path, submit_transfer
|
|
35
|
+
from rucio.db.sqla.constants import RequestState, RequestType
|
|
39
36
|
from rucio.transfertool.fts3 import FTS3Transfertool
|
|
40
37
|
from rucio.transfertool.globus import GlobusTransferTool
|
|
41
38
|
|
|
42
39
|
if TYPE_CHECKING:
|
|
40
|
+
from types import FrameType
|
|
41
|
+
|
|
42
|
+
from rucio.common.types import LoggerFunction, RSESettingsDict
|
|
43
43
|
from rucio.daemons.common import HeartbeatHandler
|
|
44
44
|
|
|
45
45
|
METRICS = MetricManager(module=__name__)
|
|
@@ -60,16 +60,16 @@ def _fetch_requests(
|
|
|
60
60
|
ignore_availability: bool,
|
|
61
61
|
filter_transfertool: Optional[str],
|
|
62
62
|
metrics: MetricManager,
|
|
63
|
-
cached_topology,
|
|
63
|
+
cached_topology: Optional[ExpiringObjectCache],
|
|
64
64
|
set_last_processed_by: bool,
|
|
65
65
|
heartbeat_handler: "HeartbeatHandler",
|
|
66
|
-
):
|
|
66
|
+
) -> tuple[bool, tuple[Topology, dict[str, RequestWithSources]]]:
|
|
67
67
|
"""
|
|
68
68
|
Fetches requests to be handled from the database
|
|
69
69
|
"""
|
|
70
70
|
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
71
71
|
|
|
72
|
-
topology = cached_topology.get() if cached_topology else Topology(ignore_availability=ignore_availability)
|
|
72
|
+
topology: Topology = cached_topology.get() if cached_topology else Topology(ignore_availability=ignore_availability)
|
|
73
73
|
topology.configure_multihop(logger=logger)
|
|
74
74
|
stopwatch = Stopwatch()
|
|
75
75
|
|
|
@@ -114,17 +114,17 @@ def _fetch_requests(
|
|
|
114
114
|
|
|
115
115
|
|
|
116
116
|
def _handle_requests(
|
|
117
|
-
batch,
|
|
117
|
+
batch: tuple[Topology, Mapping[str, RequestWithSources]],
|
|
118
118
|
*,
|
|
119
119
|
transfertools: list[str],
|
|
120
120
|
schemes: Optional[list[str]],
|
|
121
121
|
failover_schemes: Optional[list[str]],
|
|
122
122
|
max_sources: int,
|
|
123
123
|
timeout: Optional[float],
|
|
124
|
-
transfertool_kwargs,
|
|
124
|
+
transfertool_kwargs: dict,
|
|
125
125
|
metrics: MetricManager,
|
|
126
|
-
logger=logging.log,
|
|
127
|
-
):
|
|
126
|
+
logger: "LoggerFunction" = logging.log,
|
|
127
|
+
) -> None:
|
|
128
128
|
topology, requests_with_sources = batch
|
|
129
129
|
|
|
130
130
|
protocol_factory = ProtocolFactory()
|
|
@@ -168,7 +168,7 @@ def _handle_requests(
|
|
|
168
168
|
for job in grouped_jobs:
|
|
169
169
|
logger(logging.DEBUG, 'submitjob: transfers=%s, job_params=%s' % ([str(t) for t in job['transfers']], job['job_params']))
|
|
170
170
|
submit_transfer(transfertool_obj=transfertool_obj, transfers=job['transfers'], job_params=job['job_params'],
|
|
171
|
-
timeout=timeout, logger=logger)
|
|
171
|
+
timeout=timeout, logger=logger) # type: ignore (unclear whether timeout is supposed to be float or int)
|
|
172
172
|
|
|
173
173
|
|
|
174
174
|
def _get_max_time_in_queue_conf() -> dict[str, int]:
|
|
@@ -189,7 +189,7 @@ def _get_max_time_in_queue_conf() -> dict[str, int]:
|
|
|
189
189
|
|
|
190
190
|
def submitter(
|
|
191
191
|
once: bool = False,
|
|
192
|
-
rses: Optional[list[
|
|
192
|
+
rses: Optional[list["RSESettingsDict"]] = None,
|
|
193
193
|
partition_wait_time: int = 10,
|
|
194
194
|
bulk: int = 100,
|
|
195
195
|
group_bulk: int = 1,
|
|
@@ -207,9 +207,9 @@ def submitter(
|
|
|
207
207
|
request_type: Optional[list[RequestType]] = None,
|
|
208
208
|
default_lifetime: int = 172800,
|
|
209
209
|
metrics: MetricManager = METRICS,
|
|
210
|
-
cached_topology=None,
|
|
210
|
+
cached_topology: Optional[ExpiringObjectCache] = None,
|
|
211
211
|
total_threads: int = 1,
|
|
212
|
-
):
|
|
212
|
+
) -> None:
|
|
213
213
|
"""
|
|
214
214
|
Main loop to submit a new transfer primitive to a transfertool.
|
|
215
215
|
"""
|
|
@@ -219,8 +219,28 @@ def submitter(
|
|
|
219
219
|
|
|
220
220
|
partition_hash_var = config_get('conveyor', 'partition_hash_var', default=None, raise_exception=False)
|
|
221
221
|
|
|
222
|
-
|
|
223
|
-
|
|
222
|
+
config_schemes = set(config_get_list('conveyor', 'scheme', raise_exception=False) or [])
|
|
223
|
+
config_failover_schemes = set(config_get_list('conveyor', 'failover_scheme', raise_exception=False) or [])
|
|
224
|
+
|
|
225
|
+
schemes_supported_by_tt = set()
|
|
226
|
+
for transfertool in transfertools:
|
|
227
|
+
schemes_supported_by_tt.update(TRANSFERTOOL_CLASSES_BY_NAME[transfertool].supported_schemes)
|
|
228
|
+
|
|
229
|
+
schemes = config_schemes.intersection(schemes_supported_by_tt)
|
|
230
|
+
failover_schemes = config_failover_schemes.intersection(schemes_supported_by_tt)
|
|
231
|
+
|
|
232
|
+
if config_schemes and not schemes:
|
|
233
|
+
logging.critical(f'None of the configured schemes ({list(config_schemes)}) is supported '
|
|
234
|
+
f'by any configured transfertool ({transfertools}). This configuration is invalid. Aborting')
|
|
235
|
+
return
|
|
236
|
+
if config_failover_schemes and not failover_schemes:
|
|
237
|
+
logging.critical(f'None of the configured failover schemes ({list(config_failover_schemes)}) is supported '
|
|
238
|
+
f'by any configured transfertool ({transfertools}). This configuration is invalid. Aborting')
|
|
239
|
+
return
|
|
240
|
+
if config_schemes.difference(schemes):
|
|
241
|
+
logging.info(f'Following schemes filtered out: {list(config_schemes.difference(schemes))}')
|
|
242
|
+
if config_failover_schemes.difference(failover_schemes):
|
|
243
|
+
logging.info(f'Following failover schemes filtered out: {list(config_failover_schemes.difference(failover_schemes))}')
|
|
224
244
|
|
|
225
245
|
timeout = config_get_float('conveyor', 'submit_timeout', default=None, raise_exception=False)
|
|
226
246
|
|
|
@@ -262,7 +282,11 @@ def submitter(
|
|
|
262
282
|
partition_wait_time=partition_wait_time,
|
|
263
283
|
sleep_time=sleep_time,
|
|
264
284
|
activities=activities)
|
|
265
|
-
def _db_producer(
|
|
285
|
+
def _db_producer(
|
|
286
|
+
*,
|
|
287
|
+
activity: str,
|
|
288
|
+
heartbeat_handler: "HeartbeatHandler"
|
|
289
|
+
) -> tuple[bool, tuple[Topology, dict[str, RequestWithSources]]]:
|
|
266
290
|
return _fetch_requests(
|
|
267
291
|
bulk=bulk,
|
|
268
292
|
filter_transfertool=filter_transfertool,
|
|
@@ -277,12 +301,12 @@ def submitter(
|
|
|
277
301
|
heartbeat_handler=heartbeat_handler,
|
|
278
302
|
)
|
|
279
303
|
|
|
280
|
-
def _consumer(batch):
|
|
304
|
+
def _consumer(batch: tuple[Topology, Mapping[str, RequestWithSources]]) -> None:
|
|
281
305
|
return _handle_requests(
|
|
282
306
|
batch,
|
|
283
307
|
transfertools=transfertools,
|
|
284
|
-
schemes=schemes,
|
|
285
|
-
failover_schemes=failover_schemes,
|
|
308
|
+
schemes=list(schemes),
|
|
309
|
+
failover_schemes=list(failover_schemes),
|
|
286
310
|
max_sources=max_sources,
|
|
287
311
|
timeout=timeout,
|
|
288
312
|
transfertool_kwargs=transfertool_kwargs,
|
|
@@ -296,7 +320,7 @@ def submitter(
|
|
|
296
320
|
).run()
|
|
297
321
|
|
|
298
322
|
|
|
299
|
-
def stop(signum:
|
|
323
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
300
324
|
"""
|
|
301
325
|
Graceful exit.
|
|
302
326
|
"""
|
|
@@ -304,26 +328,26 @@ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) ->
|
|
|
304
328
|
|
|
305
329
|
|
|
306
330
|
def run(
|
|
307
|
-
once=False,
|
|
308
|
-
group_bulk=1,
|
|
309
|
-
group_policy='rule',
|
|
310
|
-
rses=None,
|
|
311
|
-
include_rses=None,
|
|
312
|
-
exclude_rses=None,
|
|
313
|
-
vos=None,
|
|
314
|
-
bulk=100,
|
|
315
|
-
source_strategy=None,
|
|
316
|
-
activities=None,
|
|
317
|
-
exclude_activities=None,
|
|
318
|
-
ignore_availability=False,
|
|
319
|
-
sleep_time=600,
|
|
320
|
-
max_sources=4,
|
|
321
|
-
archive_timeout_override=None,
|
|
322
|
-
total_threads=1,
|
|
331
|
+
once: bool = False,
|
|
332
|
+
group_bulk: int = 1,
|
|
333
|
+
group_policy: str = 'rule',
|
|
334
|
+
rses: Optional[list["RSESettingsDict"]] = None,
|
|
335
|
+
include_rses: Optional[str] = None,
|
|
336
|
+
exclude_rses: Optional[str] = None,
|
|
337
|
+
vos: Optional[list[str]] = None,
|
|
338
|
+
bulk: int = 100,
|
|
339
|
+
source_strategy: Optional[str] = None,
|
|
340
|
+
activities: Optional[list[str]] = None,
|
|
341
|
+
exclude_activities: Optional[list[str]] = None,
|
|
342
|
+
ignore_availability: bool = False,
|
|
343
|
+
sleep_time: int = 600,
|
|
344
|
+
max_sources: int = 4,
|
|
345
|
+
archive_timeout_override: Optional[int] = None,
|
|
346
|
+
total_threads: int = 1,
|
|
323
347
|
**_kwargs
|
|
324
|
-
):
|
|
348
|
+
) -> None:
|
|
325
349
|
"""
|
|
326
|
-
Starts up the
|
|
350
|
+
Starts up the conveyor threads.
|
|
327
351
|
"""
|
|
328
352
|
setup_logging(process_name=DAEMON_NAME)
|
|
329
353
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -17,39 +16,77 @@
|
|
|
17
16
|
Conveyor throttler is a daemon to manage rucio internal queue.
|
|
18
17
|
"""
|
|
19
18
|
import logging
|
|
19
|
+
import math
|
|
20
20
|
import threading
|
|
21
21
|
import traceback
|
|
22
22
|
from collections import defaultdict
|
|
23
|
-
from
|
|
24
|
-
from typing import TYPE_CHECKING, Optional
|
|
23
|
+
from typing import TYPE_CHECKING, Optional, TypedDict, Union
|
|
25
24
|
|
|
26
|
-
import math
|
|
27
25
|
from sqlalchemy import null
|
|
28
26
|
|
|
29
27
|
import rucio.db.sqla.util
|
|
30
28
|
from rucio.common import exception
|
|
31
29
|
from rucio.common.logging import setup_logging
|
|
32
30
|
from rucio.core.monitor import MetricManager
|
|
33
|
-
from rucio.core.request import
|
|
34
|
-
|
|
35
|
-
from rucio.core.rse import RseCollection
|
|
31
|
+
from rucio.core.request import get_request_stats, re_sync_all_transfer_limits, release_all_waiting_requests, release_waiting_requests_fifo, release_waiting_requests_grouped_fifo, reset_stale_waiting_requests, set_transfer_limit_stats
|
|
32
|
+
from rucio.core.rse import RseCollection, RseData
|
|
36
33
|
from rucio.core.transfer import applicable_rse_transfer_limits
|
|
37
|
-
from rucio.daemons.common import
|
|
34
|
+
from rucio.daemons.common import ProducerConsumerDaemon, db_workqueue
|
|
38
35
|
from rucio.db.sqla.constants import RequestState, TransferLimitDirection
|
|
39
36
|
|
|
40
37
|
if TYPE_CHECKING:
|
|
38
|
+
from collections.abc import Iterator
|
|
39
|
+
from types import FrameType
|
|
40
|
+
|
|
41
|
+
from rucio.common.types import InternalAccount, LoggerFunction
|
|
41
42
|
from rucio.daemons.common import HeartbeatHandler
|
|
42
43
|
|
|
44
|
+
class LimitDict(TypedDict):
|
|
45
|
+
activity: Optional[str]
|
|
46
|
+
direction: TransferLimitDirection
|
|
47
|
+
waitings: int
|
|
48
|
+
transfers: int
|
|
49
|
+
max_transfers: int
|
|
50
|
+
rse_expression: str
|
|
51
|
+
strategy: str
|
|
52
|
+
volume: int
|
|
53
|
+
deadline: int
|
|
54
|
+
|
|
55
|
+
class AccountStatDict(TypedDict):
|
|
56
|
+
waiting: int
|
|
57
|
+
active: int
|
|
58
|
+
residual_capacity: float
|
|
59
|
+
|
|
60
|
+
class StatDict(TypedDict):
|
|
61
|
+
accounts: AccountStatDict
|
|
62
|
+
residual_capacity: float
|
|
63
|
+
waiting: int
|
|
64
|
+
active: int
|
|
65
|
+
|
|
66
|
+
class LimitStatDict(TypedDict):
|
|
67
|
+
limit: LimitDict
|
|
68
|
+
stat: StatDict
|
|
69
|
+
|
|
70
|
+
ReleaseGroupsDict = dict[
|
|
71
|
+
tuple[
|
|
72
|
+
RseData, # source_rse
|
|
73
|
+
RseData, # dest_rse
|
|
74
|
+
str, # activity
|
|
75
|
+
],
|
|
76
|
+
list[LimitStatDict] # applicable_limits
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
|
|
43
80
|
GRACEFUL_STOP = threading.Event()
|
|
44
81
|
METRICS = MetricManager(module=__name__)
|
|
45
82
|
DAEMON_NAME = 'conveyor-throttler'
|
|
46
83
|
|
|
47
84
|
|
|
48
85
|
def throttler(
|
|
49
|
-
once=False,
|
|
50
|
-
sleep_time=600,
|
|
51
|
-
partition_wait_time=10
|
|
52
|
-
):
|
|
86
|
+
once: bool = False,
|
|
87
|
+
sleep_time: int = 600,
|
|
88
|
+
partition_wait_time: int = 10
|
|
89
|
+
) -> None:
|
|
53
90
|
"""
|
|
54
91
|
Main loop to check rse transfer limits.
|
|
55
92
|
"""
|
|
@@ -62,7 +99,11 @@ def throttler(
|
|
|
62
99
|
executable=DAEMON_NAME,
|
|
63
100
|
partition_wait_time=partition_wait_time,
|
|
64
101
|
sleep_time=sleep_time)
|
|
65
|
-
def _db_producer(
|
|
102
|
+
def _db_producer(
|
|
103
|
+
*,
|
|
104
|
+
activity: str,
|
|
105
|
+
heartbeat_handler: "HeartbeatHandler"
|
|
106
|
+
) -> tuple[bool, Optional["ReleaseGroupsDict"]]:
|
|
66
107
|
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
67
108
|
if worker_number != 0:
|
|
68
109
|
logger(logging.INFO, 'Throttler thread id is not 0, will sleep. Only thread 0 will work')
|
|
@@ -73,7 +114,7 @@ def throttler(
|
|
|
73
114
|
release_groups = _get_request_stats(rse_collection, logger=logger)
|
|
74
115
|
return True, release_groups
|
|
75
116
|
|
|
76
|
-
def _consumer(release_groups):
|
|
117
|
+
def _consumer(release_groups: Optional["ReleaseGroupsDict"]) -> None:
|
|
77
118
|
if release_groups is None:
|
|
78
119
|
return
|
|
79
120
|
logger = logging.log
|
|
@@ -82,6 +123,7 @@ def throttler(
|
|
|
82
123
|
_handle_requests(release_groups, logger=logger)
|
|
83
124
|
except Exception:
|
|
84
125
|
logger(logging.CRITICAL, "Failed to schedule requests, error: %s" % (traceback.format_exc()))
|
|
126
|
+
reset_stale_waiting_requests()
|
|
85
127
|
|
|
86
128
|
ProducerConsumerDaemon(
|
|
87
129
|
producers=[_db_producer],
|
|
@@ -90,7 +132,7 @@ def throttler(
|
|
|
90
132
|
).run()
|
|
91
133
|
|
|
92
134
|
|
|
93
|
-
def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> None:
|
|
135
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
94
136
|
"""
|
|
95
137
|
Graceful exit.
|
|
96
138
|
"""
|
|
@@ -98,9 +140,12 @@ def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> Non
|
|
|
98
140
|
GRACEFUL_STOP.set()
|
|
99
141
|
|
|
100
142
|
|
|
101
|
-
def run(
|
|
143
|
+
def run(
|
|
144
|
+
once: bool = False,
|
|
145
|
+
sleep_time: int = 600
|
|
146
|
+
) -> None:
|
|
102
147
|
"""
|
|
103
|
-
Starts up the
|
|
148
|
+
Starts up the conveyor threads.
|
|
104
149
|
"""
|
|
105
150
|
setup_logging(process_name=DAEMON_NAME)
|
|
106
151
|
|
|
@@ -114,19 +159,25 @@ class RequestGrouper:
|
|
|
114
159
|
|
|
115
160
|
class RseStatistic:
|
|
116
161
|
def __init__(self):
|
|
117
|
-
self.sources_with_limits = set()
|
|
118
|
-
self.destinations_with_limits = set()
|
|
119
|
-
self.unavailable_sources = set()
|
|
120
|
-
self.unavailable_destinations = set()
|
|
162
|
+
self.sources_with_limits: set[RseData] = set()
|
|
163
|
+
self.destinations_with_limits: set[RseData] = set()
|
|
164
|
+
self.unavailable_sources: set[RseData] = set()
|
|
165
|
+
self.unavailable_destinations: set[RseData] = set()
|
|
121
166
|
self.has_any_per_activity_limit = False
|
|
122
167
|
self.any_source_has_per_activity_limit = False
|
|
123
168
|
self.any_destination_has_per_activity_limit = False
|
|
124
169
|
|
|
125
170
|
def __init__(self):
|
|
126
|
-
self.waiting_transfer_groups = {}
|
|
171
|
+
self.waiting_transfer_groups: 'ReleaseGroupsDict' = {}
|
|
127
172
|
self.rse_stats = defaultdict(self.RseStatistic)
|
|
128
173
|
|
|
129
|
-
def record_waiting_request_group(
|
|
174
|
+
def record_waiting_request_group(
|
|
175
|
+
self,
|
|
176
|
+
source_rse: RseData,
|
|
177
|
+
dest_rse: RseData,
|
|
178
|
+
activity: str,
|
|
179
|
+
applicable_limits: list['LimitStatDict']
|
|
180
|
+
) -> None:
|
|
130
181
|
"""
|
|
131
182
|
Record a group of requests in waiting state, while computing some statistics about them.
|
|
132
183
|
"""
|
|
@@ -152,12 +203,12 @@ class RequestGrouper:
|
|
|
152
203
|
|
|
153
204
|
self.waiting_transfer_groups[source_rse, dest_rse, activity] = applicable_limits
|
|
154
205
|
|
|
155
|
-
def merged_groups(self):
|
|
206
|
+
def merged_groups(self) -> "ReleaseGroupsDict":
|
|
156
207
|
"""
|
|
157
208
|
Merge groups which can be handled together
|
|
158
209
|
"""
|
|
159
210
|
|
|
160
|
-
merged_groups = {}
|
|
211
|
+
merged_groups: "ReleaseGroupsDict" = {}
|
|
161
212
|
for (source_rse, dest_rse, activity), applicable_limits in self.waiting_transfer_groups.items():
|
|
162
213
|
|
|
163
214
|
src_info = self.rse_stats[source_rse]
|
|
@@ -187,12 +238,16 @@ class RequestGrouper:
|
|
|
187
238
|
if not src_info.has_any_per_activity_limit and not src_info.any_destination_has_per_activity_limit:
|
|
188
239
|
activity = None
|
|
189
240
|
|
|
190
|
-
merged_groups.setdefault((source_rse, dest_rse, activity), applicable_limits)
|
|
241
|
+
merged_groups.setdefault((source_rse, dest_rse, activity), applicable_limits) # type: ignore
|
|
191
242
|
|
|
192
243
|
return merged_groups
|
|
193
244
|
|
|
194
245
|
|
|
195
|
-
def _get_request_stats(
|
|
246
|
+
def _get_request_stats(
|
|
247
|
+
rse_collection: RseCollection,
|
|
248
|
+
*,
|
|
249
|
+
logger: "LoggerFunction" = logging.log
|
|
250
|
+
) -> "ReleaseGroupsDict":
|
|
196
251
|
"""
|
|
197
252
|
Group waiting requests into arbitrary groups for bulk handling.
|
|
198
253
|
The current grouping (source rse + dest rse + activity) was dictated
|
|
@@ -209,7 +264,7 @@ def _get_request_stats(rse_collection: RseCollection, *, logger=logging.log):
|
|
|
209
264
|
"""
|
|
210
265
|
logging.info("Throttler retrieve requests statistics")
|
|
211
266
|
|
|
212
|
-
db_stats = get_request_stats(
|
|
267
|
+
db_stats = get_request_stats( # type: ignore (Session parameter is missing)
|
|
213
268
|
state=[RequestState.QUEUED,
|
|
214
269
|
RequestState.SUBMITTING,
|
|
215
270
|
RequestState.SUBMITTED,
|
|
@@ -278,7 +333,7 @@ def _get_request_stats(rse_collection: RseCollection, *, logger=logging.log):
|
|
|
278
333
|
|
|
279
334
|
if state == RequestState.WAITING:
|
|
280
335
|
grouper.record_waiting_request_group(
|
|
281
|
-
source_rse=source_rse,
|
|
336
|
+
source_rse=source_rse, # type: ignore
|
|
282
337
|
dest_rse=dest_rse,
|
|
283
338
|
activity=activity,
|
|
284
339
|
applicable_limits=applicable_limits,
|
|
@@ -322,14 +377,17 @@ def _get_request_stats(rse_collection: RseCollection, *, logger=logging.log):
|
|
|
322
377
|
if waiting != limit['waitings'] or active != limit['transfers']:
|
|
323
378
|
set_transfer_limit_stats(limit['id'], waitings=waiting, transfers=active)
|
|
324
379
|
|
|
325
|
-
for account, to_release_for_account in _split_threshold_per_account(stat['accounts'], total_to_release=residual_capacity):
|
|
380
|
+
for account, to_release_for_account in _split_threshold_per_account(stat['accounts'], total_to_release=residual_capacity): # type: ignore (stat['accounts'] is not None)
|
|
326
381
|
stat['accounts'][account]['residual_capacity'] = to_release_for_account
|
|
327
382
|
|
|
328
383
|
release_groups = grouper.merged_groups()
|
|
329
384
|
return release_groups
|
|
330
385
|
|
|
331
386
|
|
|
332
|
-
def _split_threshold_per_account(
|
|
387
|
+
def _split_threshold_per_account(
|
|
388
|
+
per_account_stats: dict["InternalAccount", dict[str, float]],
|
|
389
|
+
total_to_release: float
|
|
390
|
+
) -> Union[tuple[None, int], "Iterator[tuple[InternalAccount, float]]"]:
|
|
333
391
|
"""
|
|
334
392
|
Compute how many requests to release for each account. Try to achieve a fair share of transfers between accounts.
|
|
335
393
|
:param per_account_stats: a dict with how many active and waiting transfers each account has
|
|
@@ -355,7 +413,9 @@ def _split_threshold_per_account(per_account_stats, total_to_release):
|
|
|
355
413
|
remaining_to_release -= to_release_for_account
|
|
356
414
|
|
|
357
415
|
|
|
358
|
-
def _combine_limits(
|
|
416
|
+
def _combine_limits(
|
|
417
|
+
applicable_limits: list['LimitStatDict']
|
|
418
|
+
) -> tuple[float, str, Optional[int], Optional[int]]:
|
|
359
419
|
"""
|
|
360
420
|
Take multiple limits and combines them into one single (strictest) limit which
|
|
361
421
|
respects the constraints of each initial limits. This is to handle cases like:
|
|
@@ -391,7 +451,10 @@ def _combine_limits(applicable_limits):
|
|
|
391
451
|
return to_release, strategy, volume, deadline
|
|
392
452
|
|
|
393
453
|
|
|
394
|
-
def _handle_requests(
|
|
454
|
+
def _handle_requests(
|
|
455
|
+
release_groups: "ReleaseGroupsDict",
|
|
456
|
+
logger: "LoggerFunction"
|
|
457
|
+
) -> None:
|
|
395
458
|
"""
|
|
396
459
|
Release (set to queued state) waiting requests in groups defined by release_groups.
|
|
397
460
|
|
|
@@ -440,8 +503,9 @@ def _handle_requests(release_groups, logger):
|
|
|
440
503
|
to_release_for_account = {}
|
|
441
504
|
limits_by_account = {}
|
|
442
505
|
for limit_stat in applicable_limits:
|
|
443
|
-
|
|
444
|
-
|
|
506
|
+
acc_dict = limit_stat['stat']['accounts']
|
|
507
|
+
for account, account_limit in acc_dict.items():
|
|
508
|
+
to_release_for_account[account] = min(to_release_for_account.get(account, to_release), account_limit['residual_capacity']) # type: ignore (Issue with TypedDict.__getitem__)
|
|
445
509
|
limits_by_account.setdefault(account, []).append(account_limit)
|
|
446
510
|
|
|
447
511
|
for account, to_release_account in to_release_for_account.items():
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -25,7 +24,7 @@ from rucio.common import exception
|
|
|
25
24
|
from rucio.common.logging import setup_logging
|
|
26
25
|
from rucio.common.utils import get_thread_with_periodic_running_function
|
|
27
26
|
from rucio.core.did import create_reports
|
|
28
|
-
from rucio.core.heartbeat import
|
|
27
|
+
from rucio.core.heartbeat import die, live, sanity_check
|
|
29
28
|
|
|
30
29
|
if TYPE_CHECKING:
|
|
31
30
|
from types import FrameType
|
|
@@ -35,7 +34,9 @@ graceful_stop = threading.Event()
|
|
|
35
34
|
DAEMON_NAME = 'rucio-follower'
|
|
36
35
|
|
|
37
36
|
|
|
38
|
-
def aggregate_events(
|
|
37
|
+
def aggregate_events(
|
|
38
|
+
once: bool = False
|
|
39
|
+
) -> None:
|
|
39
40
|
"""
|
|
40
41
|
Collect all the events affecting the dids followed by the corresponding account.
|
|
41
42
|
"""
|
|
@@ -70,7 +71,10 @@ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) ->
|
|
|
70
71
|
graceful_stop.set()
|
|
71
72
|
|
|
72
73
|
|
|
73
|
-
def run(
|
|
74
|
+
def run(
|
|
75
|
+
once: bool = False,
|
|
76
|
+
threads: int = 1
|
|
77
|
+
) -> None:
|
|
74
78
|
"""
|
|
75
79
|
Starts up the follower threads
|
|
76
80
|
"""
|
|
@@ -88,10 +92,10 @@ def run(once=False, threads=1):
|
|
|
88
92
|
else:
|
|
89
93
|
logging.info("starting follower threads")
|
|
90
94
|
# Run the follower daemon thrice a day
|
|
91
|
-
|
|
92
|
-
[t.start() for t in
|
|
95
|
+
thread_list = [get_thread_with_periodic_running_function(28800, aggregate_events, graceful_stop) for i in range(threads)]
|
|
96
|
+
[t.start() for t in thread_list]
|
|
93
97
|
|
|
94
98
|
logging.info("waiting for interrupts")
|
|
95
99
|
# Interruptible joins require a timeout.
|
|
96
|
-
while
|
|
97
|
-
[t.join(timeout=3.14) for t in
|
|
100
|
+
while thread_list[0].is_alive():
|
|
101
|
+
[t.join(timeout=3.14) for t in thread_list]
|
rucio/daemons/hermes/__init__.py
CHANGED