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/common.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");
|
|
@@ -22,13 +21,16 @@ import socket
|
|
|
22
21
|
import threading
|
|
23
22
|
import time
|
|
24
23
|
from collections.abc import Callable, Generator, Iterator, Sequence
|
|
25
|
-
from typing import Any, Generic, Optional, TypeVar, Union
|
|
24
|
+
from typing import TYPE_CHECKING, Any, Generic, Optional, TypeVar, Union
|
|
26
25
|
|
|
27
26
|
from rucio.common.logging import formatted_logger
|
|
28
27
|
from rucio.common.utils import PriorityQueue
|
|
29
28
|
from rucio.core import heartbeat as heartbeat_core
|
|
30
29
|
from rucio.core.monitor import MetricManager
|
|
31
30
|
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from rucio.common.types import LoggerFunction
|
|
33
|
+
|
|
32
34
|
T = TypeVar('T')
|
|
33
35
|
METRICS = MetricManager(module=__name__)
|
|
34
36
|
|
|
@@ -42,7 +44,7 @@ class HeartbeatHandler:
|
|
|
42
44
|
"""
|
|
43
45
|
:param executable: the executable name which will be set in heartbeats
|
|
44
46
|
:param renewal_interval: the interval at which the heartbeat will be renewed in the database.
|
|
45
|
-
Calls to live() in-between intervals will
|
|
47
|
+
Calls to live() in-between intervals will reuse the locally cached heartbeat.
|
|
46
48
|
"""
|
|
47
49
|
self.executable = executable
|
|
48
50
|
self._hash_executable = None
|
|
@@ -58,28 +60,32 @@ class HeartbeatHandler:
|
|
|
58
60
|
self.last_time = None
|
|
59
61
|
self.last_payload = None
|
|
60
62
|
|
|
61
|
-
def __enter__(self):
|
|
63
|
+
def __enter__(self) -> 'HeartbeatHandler':
|
|
62
64
|
heartbeat_core.sanity_check(executable=self.executable, hostname=self.hostname)
|
|
63
65
|
self.live()
|
|
64
66
|
return self
|
|
65
67
|
|
|
66
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
68
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
67
69
|
if self.last_heart_beat:
|
|
68
70
|
heartbeat_core.die(self.executable, self.hostname, self.pid, self.hb_thread)
|
|
69
71
|
if self.logger:
|
|
70
72
|
self.logger(logging.INFO, 'Heartbeat cleaned up')
|
|
71
73
|
|
|
72
74
|
@property
|
|
73
|
-
def hash_executable(self):
|
|
75
|
+
def hash_executable(self) -> str:
|
|
74
76
|
if not self._hash_executable:
|
|
75
77
|
self._hash_executable = heartbeat_core.calc_hash(self.executable)
|
|
76
78
|
return self._hash_executable
|
|
77
79
|
|
|
78
80
|
@property
|
|
79
|
-
def short_executable(self):
|
|
81
|
+
def short_executable(self) -> str:
|
|
80
82
|
return min(self.executable, self.hash_executable, key=len)
|
|
81
83
|
|
|
82
|
-
def live(
|
|
84
|
+
def live(
|
|
85
|
+
self,
|
|
86
|
+
force_renew: bool = False,
|
|
87
|
+
payload: Optional[str] = None
|
|
88
|
+
) -> tuple[int, int, Callable]:
|
|
83
89
|
"""
|
|
84
90
|
:return: a tuple: <the number of the current worker>, <total number of workers>, <decorated logger>
|
|
85
91
|
"""
|
|
@@ -171,7 +177,18 @@ def db_workqueue(
|
|
|
171
177
|
partition_wait_time: int,
|
|
172
178
|
sleep_time: int,
|
|
173
179
|
activities: Optional[Sequence[str]] = None,
|
|
174
|
-
)
|
|
180
|
+
) -> Callable[
|
|
181
|
+
[
|
|
182
|
+
Callable[
|
|
183
|
+
...,
|
|
184
|
+
Union[bool, tuple[bool, T], None]
|
|
185
|
+
]
|
|
186
|
+
],
|
|
187
|
+
Callable[
|
|
188
|
+
[],
|
|
189
|
+
Iterator[Union[T, None]]
|
|
190
|
+
]
|
|
191
|
+
]:
|
|
175
192
|
"""
|
|
176
193
|
Used to wrap a function for interacting with the database as a work queue: i.e. to select
|
|
177
194
|
a set of rows and perform some work on those rows while ensuring that two instances running in parallel don't
|
|
@@ -180,7 +197,7 @@ def db_workqueue(
|
|
|
180
197
|
|
|
181
198
|
:param once: Whether to stop after one iteration
|
|
182
199
|
:param graceful_stop: the threading.Event() object used for graceful stop of the daemon
|
|
183
|
-
:param executable: the name of the executable used for
|
|
200
|
+
:param executable: the name of the executable used for heartbeats
|
|
184
201
|
:param partition_wait_time: time to wait for database partition rebalancing before starting the actual daemon loop
|
|
185
202
|
:param sleep_time: time to sleep between the iterations of the daemon
|
|
186
203
|
:param activities: optional list of activities on which to work. The run_once_fnc will be called on activities one by one.
|
|
@@ -189,7 +206,7 @@ def db_workqueue(
|
|
|
189
206
|
def _decorate(run_once_fnc: Callable[..., Optional[Union[bool, tuple[bool, T]]]]) -> Callable[[], Iterator[Optional[T]]]:
|
|
190
207
|
|
|
191
208
|
@functools.wraps(run_once_fnc)
|
|
192
|
-
def _generator():
|
|
209
|
+
def _generator() -> Iterator[T]:
|
|
193
210
|
|
|
194
211
|
with HeartbeatHandler(executable=executable, renewal_interval=sleep_time - 1) as heartbeat_handler:
|
|
195
212
|
logger = heartbeat_handler.logger
|
|
@@ -254,7 +271,8 @@ def run_daemon(
|
|
|
254
271
|
partition_wait_time: int,
|
|
255
272
|
sleep_time: int,
|
|
256
273
|
run_once_fnc: Callable[..., Optional[Union[bool, tuple[bool, Any]]]],
|
|
257
|
-
activities: Optional[list[str]] = None
|
|
274
|
+
activities: Optional[list[str]] = None
|
|
275
|
+
) -> None:
|
|
258
276
|
"""
|
|
259
277
|
Run the daemon loop and call the function run_once_fnc at each iteration
|
|
260
278
|
"""
|
|
@@ -277,7 +295,13 @@ class ProducerConsumerDaemon(Generic[T]):
|
|
|
277
295
|
Daemon which connects N producers with M consumers via a queue.
|
|
278
296
|
"""
|
|
279
297
|
|
|
280
|
-
def __init__(
|
|
298
|
+
def __init__(
|
|
299
|
+
self,
|
|
300
|
+
producers: Sequence[Callable[[], Iterator[T]]],
|
|
301
|
+
consumers: Sequence[Callable[..., None]],
|
|
302
|
+
graceful_stop: threading.Event,
|
|
303
|
+
logger: "LoggerFunction" = logging.log
|
|
304
|
+
):
|
|
281
305
|
self.producers = producers
|
|
282
306
|
self.consumers = consumers
|
|
283
307
|
|
|
@@ -292,7 +316,7 @@ class ProducerConsumerDaemon(Generic[T]):
|
|
|
292
316
|
self,
|
|
293
317
|
it: Callable[[], Iterator[T]],
|
|
294
318
|
wait_for_consumers: bool = False
|
|
295
|
-
):
|
|
319
|
+
) -> None:
|
|
296
320
|
"""
|
|
297
321
|
Iterate over the generator function and put the extracted elements into the queue.
|
|
298
322
|
|
|
@@ -328,7 +352,7 @@ class ProducerConsumerDaemon(Generic[T]):
|
|
|
328
352
|
def _consume(
|
|
329
353
|
self,
|
|
330
354
|
fnc: Callable[[T], Any]
|
|
331
|
-
):
|
|
355
|
+
) -> None:
|
|
332
356
|
"""
|
|
333
357
|
Wait for elements to arrive via the queue and call the given function on each element.
|
|
334
358
|
|
|
@@ -349,9 +373,9 @@ class ProducerConsumerDaemon(Generic[T]):
|
|
|
349
373
|
finally:
|
|
350
374
|
self.queue.task_done()
|
|
351
375
|
|
|
352
|
-
def run(self):
|
|
376
|
+
def run(self) -> None:
|
|
353
377
|
|
|
354
|
-
producer_threads = []
|
|
378
|
+
producer_threads: list[threading.Thread] = []
|
|
355
379
|
for i, producer in enumerate(self.producers):
|
|
356
380
|
thread = threading.Thread(
|
|
357
381
|
target=self._produce,
|
|
@@ -364,7 +388,7 @@ class ProducerConsumerDaemon(Generic[T]):
|
|
|
364
388
|
thread.start()
|
|
365
389
|
producer_threads.append(thread)
|
|
366
390
|
|
|
367
|
-
consumer_threads = []
|
|
391
|
+
consumer_threads: list[threading.Thread] = []
|
|
368
392
|
for i, consumer in enumerate(self.consumers):
|
|
369
393
|
thread = threading.Thread(
|
|
370
394
|
target=self._consume,
|
rucio/daemons/conveyor/common.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");
|
|
@@ -22,37 +21,52 @@ import functools
|
|
|
22
21
|
import itertools
|
|
23
22
|
import logging
|
|
24
23
|
import re
|
|
25
|
-
from typing import TYPE_CHECKING
|
|
24
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
26
25
|
|
|
27
26
|
from rucio.common.config import config_get_bool
|
|
28
|
-
from rucio.common.
|
|
29
|
-
|
|
27
|
+
from rucio.common.constants import RseAttr
|
|
28
|
+
from rucio.common.exception import DatabaseException, DuplicateFileTransferSubmission, InvalidRSEExpression, RequestNotFound, TransferToolTimeout, TransferToolWrongAnswer, VONotFound
|
|
30
29
|
from rucio.common.stopwatch import Stopwatch
|
|
31
|
-
from rucio.core import request as request_core
|
|
30
|
+
from rucio.core import request as request_core
|
|
31
|
+
from rucio.core import transfer as transfer_core
|
|
32
32
|
from rucio.core.monitor import MetricManager
|
|
33
33
|
from rucio.core.replica import add_replicas, tombstone_from_delay, update_replica_state
|
|
34
|
-
from rucio.core.request import
|
|
34
|
+
from rucio.core.request import queue_requests, transition_request_state
|
|
35
35
|
from rucio.core.rse import list_rses
|
|
36
36
|
from rucio.core.rse_expression_parser import parse_expression
|
|
37
37
|
from rucio.core.transfer import build_transfer_paths
|
|
38
38
|
from rucio.core.vo import list_vos
|
|
39
39
|
from rucio.db.sqla import models
|
|
40
|
-
from rucio.db.sqla.constants import
|
|
40
|
+
from rucio.db.sqla.constants import ReplicaState, RequestState
|
|
41
41
|
from rucio.db.sqla.session import transactional_session
|
|
42
42
|
from rucio.rse import rsemanager as rsemgr
|
|
43
43
|
|
|
44
44
|
if TYPE_CHECKING:
|
|
45
|
-
from collections.abc import
|
|
46
|
-
|
|
47
|
-
from rucio.core.transfer import DirectTransferDefinition
|
|
48
|
-
from rucio.transfertool.transfertool import TransferToolBuilder
|
|
45
|
+
from collections.abc import Iterable, Mapping, Sequence
|
|
46
|
+
|
|
49
47
|
from sqlalchemy.orm import Session
|
|
50
48
|
|
|
49
|
+
from rucio.common.types import InternalAccount, LoggerFunction, RSESettingsDict
|
|
50
|
+
from rucio.core.request import DirectTransfer, RequestWithSources
|
|
51
|
+
from rucio.core.topology import Topology
|
|
52
|
+
from rucio.core.transfer import ProtocolFactory
|
|
53
|
+
from rucio.transfertool.transfertool import Transfertool, TransferToolBuilder
|
|
54
|
+
|
|
51
55
|
METRICS = MetricManager(module=__name__)
|
|
52
56
|
|
|
53
57
|
|
|
54
|
-
def pick_and_prepare_submission_path(
|
|
55
|
-
|
|
58
|
+
def pick_and_prepare_submission_path(
|
|
59
|
+
requests_with_sources: "Mapping[str, RequestWithSources]",
|
|
60
|
+
topology: "Topology",
|
|
61
|
+
protocol_factory: "ProtocolFactory",
|
|
62
|
+
default_tombstone_delay: int = transfer_core.DEFAULT_MULTIHOP_TOMBSTONE_DELAY,
|
|
63
|
+
admin_accounts: Optional[set["InternalAccount"]] = None,
|
|
64
|
+
schemes: Optional["Sequence[str]"] = None,
|
|
65
|
+
failover_schemes: Optional["Sequence[str]"] = None,
|
|
66
|
+
max_sources: int = 4,
|
|
67
|
+
transfertools: Optional["Sequence[str]"] = None,
|
|
68
|
+
logger: "LoggerFunction" = logging.log
|
|
69
|
+
) -> dict["TransferToolBuilder", list[list["DirectTransfer"]]]:
|
|
56
70
|
"""
|
|
57
71
|
For each transfer, pick a (sub)path; and a transfertool to be used to submit that (sub)path
|
|
58
72
|
"""
|
|
@@ -119,22 +133,22 @@ def pick_and_prepare_submission_path(requests_with_sources, topology, protocol_f
|
|
|
119
133
|
reqs_no_source.update(reqs_no_host)
|
|
120
134
|
if reqs_no_source:
|
|
121
135
|
logger(logging.INFO, "Marking requests as no-sources: %s", reqs_no_source)
|
|
122
|
-
request_core.
|
|
136
|
+
request_core.transition_requests_state_if_possible(reqs_no_source, RequestState.NO_SOURCES, logger=logger)
|
|
123
137
|
if reqs_only_tape_source:
|
|
124
138
|
logger(logging.INFO, "Marking requests as only-tape-sources: %s", reqs_only_tape_source)
|
|
125
|
-
request_core.
|
|
139
|
+
request_core.transition_requests_state_if_possible(reqs_only_tape_source, RequestState.ONLY_TAPE_SOURCES, logger=logger)
|
|
126
140
|
if reqs_scheme_mismatch:
|
|
127
141
|
logger(logging.INFO, "Marking requests as scheme-mismatch: %s", reqs_scheme_mismatch)
|
|
128
|
-
request_core.
|
|
142
|
+
request_core.transition_requests_state_if_possible(reqs_scheme_mismatch, RequestState.MISMATCH_SCHEME, logger=logger)
|
|
129
143
|
|
|
130
144
|
return paths_by_transfertool_builder
|
|
131
145
|
|
|
132
146
|
|
|
133
147
|
def __assign_to_transfertool(
|
|
134
|
-
transfer_path:
|
|
135
|
-
transfertools:
|
|
136
|
-
logger: "
|
|
137
|
-
) ->
|
|
148
|
+
transfer_path: list["DirectTransfer"],
|
|
149
|
+
transfertools: Optional["Iterable[str]"],
|
|
150
|
+
logger: "LoggerFunction",
|
|
151
|
+
) -> list[tuple[list["DirectTransfer"], Optional["TransferToolBuilder"]]]:
|
|
138
152
|
"""
|
|
139
153
|
Iterate over a multihop path and assign sub-paths to transfertools in chucks from left to right.
|
|
140
154
|
|
|
@@ -174,11 +188,11 @@ def __assign_to_transfertool(
|
|
|
174
188
|
|
|
175
189
|
|
|
176
190
|
def assign_paths_to_transfertool_and_create_hops(
|
|
177
|
-
candidate_paths_by_request_id: "
|
|
191
|
+
candidate_paths_by_request_id: "Mapping[str, Sequence[DirectTransfer]]",
|
|
178
192
|
default_tombstone_delay: int,
|
|
179
|
-
transfertools:
|
|
180
|
-
logger: "
|
|
181
|
-
) -> "tuple[dict[TransferToolBuilder, list[
|
|
193
|
+
transfertools: Optional["Sequence[str]"] = None,
|
|
194
|
+
logger: "LoggerFunction" = logging.log,
|
|
195
|
+
) -> "tuple[dict[TransferToolBuilder, list[list[DirectTransfer]]], set[str]]":
|
|
182
196
|
"""
|
|
183
197
|
for each request, pick the first path which can be submitted by one of the transfertools.
|
|
184
198
|
If the chosen path is multihop, create all missing intermediate requests and replicas.
|
|
@@ -214,13 +228,13 @@ def assign_paths_to_transfertool_and_create_hops(
|
|
|
214
228
|
@transactional_session
|
|
215
229
|
def __assign_paths_to_transfertool_and_create_hops(
|
|
216
230
|
request_id: str,
|
|
217
|
-
candidate_paths: "Sequence[list[
|
|
231
|
+
candidate_paths: "Sequence[list[DirectTransfer]]",
|
|
218
232
|
default_tombstone_delay: int,
|
|
219
|
-
transfertools: "Optional[
|
|
233
|
+
transfertools: "Optional[Sequence[str]]" = None,
|
|
220
234
|
*,
|
|
221
|
-
logger: "
|
|
235
|
+
logger: "LoggerFunction" = logging.log,
|
|
222
236
|
session: "Session",
|
|
223
|
-
) -> "tuple[Optional[list[
|
|
237
|
+
) -> "tuple[Optional[list[DirectTransfer]], Optional[TransferToolBuilder]]":
|
|
224
238
|
"""
|
|
225
239
|
Out of a sequence of candidate paths for the given request, pick the first path which can
|
|
226
240
|
be submitted by one of the transfertools.
|
|
@@ -231,9 +245,9 @@ def __assign_paths_to_transfertool_and_create_hops(
|
|
|
231
245
|
|
|
232
246
|
# Selects the first path which can be submitted using a chain of supported transfertools
|
|
233
247
|
# and for which the creation of intermediate hops (if it is a multihop) works correctly
|
|
234
|
-
best_path =
|
|
248
|
+
best_path = []
|
|
235
249
|
builder_to_use = None
|
|
236
|
-
hops_to_submit =
|
|
250
|
+
hops_to_submit = []
|
|
237
251
|
must_skip_submission = False
|
|
238
252
|
|
|
239
253
|
tt_assignments = [(transfer_path, __assign_to_transfertool(transfer_path, transfertools, logger=logger))
|
|
@@ -290,10 +304,10 @@ def __assign_paths_to_transfertool_and_create_hops(
|
|
|
290
304
|
|
|
291
305
|
@transactional_session
|
|
292
306
|
def __create_missing_replicas_and_requests(
|
|
293
|
-
transfer_path: "list[
|
|
307
|
+
transfer_path: "list[DirectTransfer]",
|
|
294
308
|
default_tombstone_delay: int,
|
|
295
309
|
*,
|
|
296
|
-
logger: "
|
|
310
|
+
logger: "LoggerFunction",
|
|
297
311
|
session: "Session"
|
|
298
312
|
) -> tuple[bool, bool]:
|
|
299
313
|
"""
|
|
@@ -310,7 +324,7 @@ def __create_missing_replicas_and_requests(
|
|
|
310
324
|
if rws.request_id:
|
|
311
325
|
continue
|
|
312
326
|
|
|
313
|
-
tombstone_delay = rws.dest_rse.attributes.get(
|
|
327
|
+
tombstone_delay = rws.dest_rse.attributes.get(RseAttr.MULTIHOP_TOMBSTONE_DELAY, default_tombstone_delay)
|
|
314
328
|
try:
|
|
315
329
|
tombstone = tombstone_from_delay(tombstone_delay)
|
|
316
330
|
except ValueError:
|
|
@@ -376,7 +390,13 @@ def __create_missing_replicas_and_requests(
|
|
|
376
390
|
return creation_successful, must_skip_submission
|
|
377
391
|
|
|
378
392
|
|
|
379
|
-
def submit_transfer(
|
|
393
|
+
def submit_transfer(
|
|
394
|
+
transfertool_obj: "Transfertool",
|
|
395
|
+
transfers: "Sequence[DirectTransfer]",
|
|
396
|
+
job_params: dict[str, str],
|
|
397
|
+
timeout: Optional[int] = None,
|
|
398
|
+
logger: "LoggerFunction" = logging.log
|
|
399
|
+
) -> None:
|
|
380
400
|
"""
|
|
381
401
|
Submit a transfer or staging request
|
|
382
402
|
|
|
@@ -396,7 +416,7 @@ def submit_transfer(transfertool_obj, transfers, job_params, timeout=None, logge
|
|
|
396
416
|
return
|
|
397
417
|
except Exception:
|
|
398
418
|
logger(logging.ERROR, 'Failed to prepare requests %s state to SUBMITTING. Mark it SUBMISSION_FAILED and abort submission.' % [str(t.rws) for t in transfers], exc_info=True)
|
|
399
|
-
|
|
419
|
+
transition_request_state(request_id=transfer.rws.request_id, state=RequestState.SUBMISSION_FAILED)
|
|
400
420
|
return
|
|
401
421
|
|
|
402
422
|
try:
|
|
@@ -408,7 +428,13 @@ def submit_transfer(transfertool_obj, transfers, job_params, timeout=None, logge
|
|
|
408
428
|
_submit_transfers(transfertool_obj, [transfer], job_params, timeout, logger)
|
|
409
429
|
|
|
410
430
|
|
|
411
|
-
def _submit_transfers(
|
|
431
|
+
def _submit_transfers(
|
|
432
|
+
transfertool_obj: "Transfertool",
|
|
433
|
+
transfers: "Sequence[DirectTransfer]",
|
|
434
|
+
job_params: dict[str, str],
|
|
435
|
+
timeout: Optional[int] = None,
|
|
436
|
+
logger: "LoggerFunction" = logging.log
|
|
437
|
+
) -> None:
|
|
412
438
|
"""
|
|
413
439
|
helper function for submit_transfers. Performs the actual submission of one or more transfers.
|
|
414
440
|
|
|
@@ -470,7 +496,13 @@ def _submit_transfers(transfertool_obj, transfers, job_params, timeout=None, log
|
|
|
470
496
|
logger(logging.ERROR, 'Failed to cancel transfers %s on %s with error' % (eid, transfertool_obj), exc_info=True)
|
|
471
497
|
|
|
472
498
|
|
|
473
|
-
def get_conveyor_rses(
|
|
499
|
+
def get_conveyor_rses(
|
|
500
|
+
rses: Optional["Sequence[Mapping[str, Any]]"] = None,
|
|
501
|
+
include_rses: Optional[str] = None,
|
|
502
|
+
exclude_rses: Optional[str] = None,
|
|
503
|
+
vos: Optional["Sequence[str]"] = None,
|
|
504
|
+
logger: "LoggerFunction" = logging.log
|
|
505
|
+
) -> list["RSESettingsDict"]:
|
|
474
506
|
"""
|
|
475
507
|
Get a list of rses for conveyor
|
|
476
508
|
|
|
@@ -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");
|
|
@@ -23,8 +22,7 @@ import logging
|
|
|
23
22
|
import os
|
|
24
23
|
import re
|
|
25
24
|
import threading
|
|
26
|
-
from
|
|
27
|
-
from typing import TYPE_CHECKING, Optional
|
|
25
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional
|
|
28
26
|
from urllib.parse import urlparse
|
|
29
27
|
|
|
30
28
|
from dogpile.cache.api import NoValue
|
|
@@ -32,22 +30,27 @@ from sqlalchemy.exc import DatabaseError
|
|
|
32
30
|
|
|
33
31
|
import rucio.db.sqla.util
|
|
34
32
|
from rucio.common.cache import make_region_memcached
|
|
35
|
-
from rucio.common.config import
|
|
36
|
-
from rucio.common.exception import DatabaseException,
|
|
33
|
+
from rucio.common.config import config_get_bool, config_get_list
|
|
34
|
+
from rucio.common.exception import DatabaseException, ReplicaNotFound, RequestNotFound, RSEProtocolNotSupported, UnsupportedOperation
|
|
37
35
|
from rucio.common.logging import setup_logging
|
|
38
36
|
from rucio.common.stopwatch import Stopwatch
|
|
39
|
-
from rucio.common.types import InternalAccount
|
|
37
|
+
from rucio.common.types import InternalAccount, LoggerFunction, RequestDict
|
|
40
38
|
from rucio.common.utils import chunks
|
|
41
|
-
from rucio.core import
|
|
39
|
+
from rucio.core import replica as replica_core
|
|
40
|
+
from rucio.core import request as request_core
|
|
42
41
|
from rucio.core.monitor import MetricManager
|
|
43
42
|
from rucio.core.rse import list_rses
|
|
43
|
+
from rucio.core.topology import ExpiringObjectCache, Topology
|
|
44
44
|
from rucio.core.transfer import ProtocolFactory
|
|
45
|
-
from rucio.
|
|
46
|
-
from rucio.
|
|
47
|
-
from rucio.db.sqla.constants import RequestState, RequestType, ReplicaState, BadFilesStatus
|
|
45
|
+
from rucio.daemons.common import ProducerConsumerDaemon, db_workqueue
|
|
46
|
+
from rucio.db.sqla.constants import MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED, ORACLE_DEADLOCK_DETECTED_REGEX, ORACLE_RESOURCE_BUSY_REGEX, BadFilesStatus, ReplicaState, RequestState, RequestType
|
|
48
47
|
from rucio.db.sqla.session import transactional_session
|
|
49
48
|
|
|
50
49
|
if TYPE_CHECKING:
|
|
50
|
+
from types import FrameType
|
|
51
|
+
|
|
52
|
+
from sqlalchemy.orm import Session
|
|
53
|
+
|
|
51
54
|
from rucio.daemons.common import HeartbeatHandler
|
|
52
55
|
|
|
53
56
|
GRACEFUL_STOP = threading.Event()
|
|
@@ -59,12 +62,12 @@ FAILED_DURING_SUBMISSION_DELAY = datetime.timedelta(minutes=120)
|
|
|
59
62
|
|
|
60
63
|
|
|
61
64
|
def _fetch_requests(
|
|
62
|
-
db_bulk,
|
|
65
|
+
db_bulk: int,
|
|
63
66
|
set_last_processed_by: bool,
|
|
64
|
-
cached_topology,
|
|
65
|
-
heartbeat_handler,
|
|
66
|
-
activity,
|
|
67
|
-
):
|
|
67
|
+
cached_topology: Optional[ExpiringObjectCache],
|
|
68
|
+
heartbeat_handler: "HeartbeatHandler",
|
|
69
|
+
activity: str,
|
|
70
|
+
) -> tuple[bool, tuple[list[dict[str, Any]], Topology]]:
|
|
68
71
|
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
69
72
|
|
|
70
73
|
logger(logging.DEBUG, 'Working on activity %s', activity)
|
|
@@ -109,13 +112,13 @@ def _fetch_requests(
|
|
|
109
112
|
|
|
110
113
|
|
|
111
114
|
def _handle_requests(
|
|
112
|
-
batch,
|
|
113
|
-
bulk,
|
|
114
|
-
suspicious_patterns,
|
|
115
|
-
retry_protocol_mismatches,
|
|
115
|
+
batch: tuple[list[RequestDict], Topology],
|
|
116
|
+
bulk: int,
|
|
117
|
+
suspicious_patterns: list[re.Pattern],
|
|
118
|
+
retry_protocol_mismatches: bool,
|
|
116
119
|
*,
|
|
117
|
-
logger=logging.log,
|
|
118
|
-
):
|
|
120
|
+
logger: LoggerFunction = logging.log,
|
|
121
|
+
) -> None:
|
|
119
122
|
reqs, topology = batch
|
|
120
123
|
if not reqs:
|
|
121
124
|
return
|
|
@@ -137,22 +140,22 @@ def _handle_requests(
|
|
|
137
140
|
logger(logging.DEBUG, 'Finish to update %s finished requests in %s seconds', len(reqs), total_stopwatch.elapsed)
|
|
138
141
|
|
|
139
142
|
except (DatabaseException, DatabaseError) as error:
|
|
140
|
-
if re.match(
|
|
143
|
+
if re.match(ORACLE_RESOURCE_BUSY_REGEX, error.args[0]) or re.match(ORACLE_DEADLOCK_DETECTED_REGEX, error.args[0]) or MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED in error.args[0]:
|
|
141
144
|
logger(logging.WARNING, 'Lock detected when handling request - skipping: %s', str(error))
|
|
142
145
|
else:
|
|
143
146
|
raise
|
|
144
147
|
|
|
145
148
|
|
|
146
149
|
def finisher(
|
|
147
|
-
once=False,
|
|
148
|
-
sleep_time=60,
|
|
149
|
-
activities=None,
|
|
150
|
-
bulk=100,
|
|
151
|
-
db_bulk=1000,
|
|
152
|
-
partition_wait_time=10,
|
|
153
|
-
cached_topology=None,
|
|
154
|
-
total_threads=1,
|
|
155
|
-
):
|
|
150
|
+
once: bool = False,
|
|
151
|
+
sleep_time: int = 60,
|
|
152
|
+
activities: Optional[list[str]] = None,
|
|
153
|
+
bulk: int = 100,
|
|
154
|
+
db_bulk: int = 1000,
|
|
155
|
+
partition_wait_time: int = 10,
|
|
156
|
+
cached_topology: Optional[ExpiringObjectCache] = None,
|
|
157
|
+
total_threads: int = 1,
|
|
158
|
+
) -> None:
|
|
156
159
|
"""
|
|
157
160
|
Main loop to update the replicas and rules based on finished requests.
|
|
158
161
|
"""
|
|
@@ -176,7 +179,11 @@ def finisher(
|
|
|
176
179
|
sleep_time=sleep_time,
|
|
177
180
|
activities=activities,
|
|
178
181
|
)
|
|
179
|
-
def _db_producer(
|
|
182
|
+
def _db_producer(
|
|
183
|
+
*,
|
|
184
|
+
activity: str,
|
|
185
|
+
heartbeat_handler: "HeartbeatHandler"
|
|
186
|
+
) -> tuple[bool, tuple[list[dict[str, Any]], Topology]]:
|
|
180
187
|
return _fetch_requests(
|
|
181
188
|
db_bulk=db_bulk,
|
|
182
189
|
cached_topology=cached_topology,
|
|
@@ -185,7 +192,7 @@ def finisher(
|
|
|
185
192
|
heartbeat_handler=heartbeat_handler,
|
|
186
193
|
)
|
|
187
194
|
|
|
188
|
-
def _consumer(batch):
|
|
195
|
+
def _consumer(batch: tuple[list[RequestDict], Topology]) -> None:
|
|
189
196
|
return _handle_requests(
|
|
190
197
|
batch=batch,
|
|
191
198
|
bulk=bulk,
|
|
@@ -200,7 +207,7 @@ def finisher(
|
|
|
200
207
|
).run()
|
|
201
208
|
|
|
202
209
|
|
|
203
|
-
def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> None:
|
|
210
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
204
211
|
"""
|
|
205
212
|
Graceful exit.
|
|
206
213
|
"""
|
|
@@ -208,9 +215,16 @@ def stop(signum: Optional[int] = None, frame: Optional[FrameType] = None) -> Non
|
|
|
208
215
|
GRACEFUL_STOP.set()
|
|
209
216
|
|
|
210
217
|
|
|
211
|
-
def run(
|
|
218
|
+
def run(
|
|
219
|
+
once: bool = False,
|
|
220
|
+
total_threads: int = 1,
|
|
221
|
+
sleep_time: int = 60,
|
|
222
|
+
activities: Optional[list[str]] = None,
|
|
223
|
+
bulk: int = 100,
|
|
224
|
+
db_bulk: int = 1000
|
|
225
|
+
) -> None:
|
|
212
226
|
"""
|
|
213
|
-
Starts up the
|
|
227
|
+
Starts up the conveyor threads.
|
|
214
228
|
"""
|
|
215
229
|
setup_logging(process_name=DAEMON_NAME)
|
|
216
230
|
|
|
@@ -229,7 +243,13 @@ def run(once=False, total_threads=1, sleep_time=60, activities=None, bulk=100, d
|
|
|
229
243
|
)
|
|
230
244
|
|
|
231
245
|
|
|
232
|
-
def _finish_requests(
|
|
246
|
+
def _finish_requests(
|
|
247
|
+
topology: Topology,
|
|
248
|
+
reqs: list[RequestDict],
|
|
249
|
+
suspicious_patterns: list[re.Pattern],
|
|
250
|
+
retry_protocol_mismatches: bool,
|
|
251
|
+
logger: LoggerFunction = logging.log
|
|
252
|
+
) -> None:
|
|
233
253
|
"""
|
|
234
254
|
Used by finisher to handle terminated requests,
|
|
235
255
|
|
|
@@ -325,11 +345,11 @@ def _finish_requests(topology: "Topology", reqs, suspicious_patterns, retry_prot
|
|
|
325
345
|
__handle_terminated_replicas(replicas, logger=logger)
|
|
326
346
|
|
|
327
347
|
|
|
328
|
-
def __get_undeterministic_rses(logger=logging.log):
|
|
348
|
+
def __get_undeterministic_rses(logger: LoggerFunction = logging.log) -> list[str]:
|
|
329
349
|
"""
|
|
330
350
|
Get the undeterministic rses from the database
|
|
331
351
|
|
|
332
|
-
:returns: List of
|
|
352
|
+
:returns: List of undeterministic rses
|
|
333
353
|
"""
|
|
334
354
|
key = 'undeterministic_rses'
|
|
335
355
|
result = REGION.get(key)
|
|
@@ -343,7 +363,11 @@ def __get_undeterministic_rses(logger=logging.log):
|
|
|
343
363
|
return result
|
|
344
364
|
|
|
345
365
|
|
|
346
|
-
def __check_suspicious_files(
|
|
366
|
+
def __check_suspicious_files(
|
|
367
|
+
req: RequestDict,
|
|
368
|
+
suspicious_patterns: list[re.Pattern],
|
|
369
|
+
logger: LoggerFunction = logging.log
|
|
370
|
+
) -> bool:
|
|
347
371
|
"""
|
|
348
372
|
Check suspicious files when a transfer failed.
|
|
349
373
|
|
|
@@ -376,7 +400,10 @@ def __check_suspicious_files(req, suspicious_patterns, logger=logging.log):
|
|
|
376
400
|
return is_suspicious
|
|
377
401
|
|
|
378
402
|
|
|
379
|
-
def __handle_terminated_replicas(
|
|
403
|
+
def __handle_terminated_replicas(
|
|
404
|
+
replicas: dict[str, dict[str, list[dict[str, Any]]]],
|
|
405
|
+
logger: LoggerFunction = logging.log
|
|
406
|
+
) -> None:
|
|
380
407
|
"""
|
|
381
408
|
Used by finisher to handle available and unavailable replicas.
|
|
382
409
|
|
|
@@ -394,14 +421,14 @@ def __handle_terminated_replicas(replicas, logger=logging.log):
|
|
|
394
421
|
try:
|
|
395
422
|
__update_replica(replica, logger=logger)
|
|
396
423
|
except (DatabaseException, DatabaseError) as error:
|
|
397
|
-
if re.match(
|
|
424
|
+
if re.match(ORACLE_RESOURCE_BUSY_REGEX, error.args[0]) or re.match(ORACLE_DEADLOCK_DETECTED_REGEX, error.args[0]) or MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED in error.args[0]:
|
|
398
425
|
logger(logging.WARNING, "Locks detected when handling replica %s:%s at RSE %s", replica['scope'], replica['name'], replica['rse_id'])
|
|
399
426
|
else:
|
|
400
427
|
logger(logging.ERROR, "Could not finish handling replicas %s:%s at RSE %s", replica['scope'], replica['name'], replica['rse_id'], exc_info=True)
|
|
401
428
|
except Exception as error:
|
|
402
429
|
logger(logging.ERROR, "Something unexpected happened when updating replica state for transfer %s:%s at %s (%s)", replica['scope'], replica['name'], replica['rse_id'], str(error))
|
|
403
430
|
except (DatabaseException, DatabaseError) as error:
|
|
404
|
-
if re.match(
|
|
431
|
+
if re.match(ORACLE_RESOURCE_BUSY_REGEX, error.args[0]) or re.match(ORACLE_DEADLOCK_DETECTED_REGEX, error.args[0]) or MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED in error.args[0]:
|
|
405
432
|
logger(logging.WARNING, "Locks detected when handling replicas on %s rule %s, update updated time.", req_type, rule_id)
|
|
406
433
|
try:
|
|
407
434
|
request_core.touch_requests_by_rule(rule_id)
|
|
@@ -414,9 +441,14 @@ def __handle_terminated_replicas(replicas, logger=logging.log):
|
|
|
414
441
|
|
|
415
442
|
|
|
416
443
|
@transactional_session
|
|
417
|
-
def __update_bulk_replicas(
|
|
444
|
+
def __update_bulk_replicas(
|
|
445
|
+
replicas: list[dict[str, Any]],
|
|
446
|
+
*,
|
|
447
|
+
session: "Session",
|
|
448
|
+
logger: LoggerFunction = logging.log
|
|
449
|
+
) -> Literal[True]:
|
|
418
450
|
"""
|
|
419
|
-
Used by finisher to handle available and unavailable replicas
|
|
451
|
+
Used by finisher to handle available and unavailable replicas belongs to same rule in bulk way.
|
|
420
452
|
|
|
421
453
|
:param replicas: List of replicas.
|
|
422
454
|
:param session: The database session to use.
|
|
@@ -436,7 +468,12 @@ def __update_bulk_replicas(replicas, *, session, logger=logging.log):
|
|
|
436
468
|
|
|
437
469
|
|
|
438
470
|
@transactional_session
|
|
439
|
-
def __update_replica(
|
|
471
|
+
def __update_replica(
|
|
472
|
+
replica: dict[str, Any],
|
|
473
|
+
*,
|
|
474
|
+
session: "Session",
|
|
475
|
+
logger: LoggerFunction = logging.log
|
|
476
|
+
) -> None:
|
|
440
477
|
"""
|
|
441
478
|
Used by finisher to update a replica to a finished state.
|
|
442
479
|
|