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/hermes/hermes.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");
|
|
@@ -31,10 +30,11 @@ import threading
|
|
|
31
30
|
import time
|
|
32
31
|
from configparser import NoOptionError, NoSectionError
|
|
33
32
|
from email.mime.text import MIMEText
|
|
34
|
-
from typing import TYPE_CHECKING
|
|
33
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
|
35
34
|
|
|
36
35
|
import requests
|
|
37
36
|
import stomp
|
|
37
|
+
from requests.auth import HTTPBasicAuth
|
|
38
38
|
|
|
39
39
|
import rucio.db.sqla.util
|
|
40
40
|
from rucio.common.config import (
|
|
@@ -50,10 +50,12 @@ from rucio.core.monitor import MetricManager
|
|
|
50
50
|
from rucio.daemons.common import run_daemon
|
|
51
51
|
|
|
52
52
|
if TYPE_CHECKING:
|
|
53
|
-
from collections.abc import
|
|
53
|
+
from collections.abc import Iterable, Sequence
|
|
54
54
|
from types import FrameType
|
|
55
|
-
from typing import Optional
|
|
56
55
|
|
|
56
|
+
from stomp.utils import Frame
|
|
57
|
+
|
|
58
|
+
from rucio.common.types import LoggerFunction
|
|
57
59
|
from rucio.daemons.common import HeartbeatHandler
|
|
58
60
|
|
|
59
61
|
logging.getLogger("requests").setLevel(logging.CRITICAL)
|
|
@@ -69,7 +71,7 @@ RECONNECT_COUNTER = METRICS.counter(
|
|
|
69
71
|
)
|
|
70
72
|
|
|
71
73
|
|
|
72
|
-
def default(datetype):
|
|
74
|
+
def default(datetype: Union[datetime.date, datetime.datetime]) -> str:
|
|
73
75
|
if isinstance(datetype, (datetime.date, datetime.datetime)):
|
|
74
76
|
return datetype.isoformat()
|
|
75
77
|
|
|
@@ -79,20 +81,28 @@ class HermesListener(stomp.ConnectionListener):
|
|
|
79
81
|
Hermes Listener
|
|
80
82
|
"""
|
|
81
83
|
|
|
82
|
-
def __init__(self, broker):
|
|
84
|
+
def __init__(self, broker: str):
|
|
83
85
|
"""
|
|
84
86
|
__init__
|
|
85
87
|
"""
|
|
86
88
|
self.__broker = broker
|
|
87
89
|
|
|
88
|
-
def on_error(self, frame):
|
|
90
|
+
def on_error(self, frame: "Frame") -> None:
|
|
89
91
|
"""
|
|
90
92
|
Error handler
|
|
91
93
|
"""
|
|
92
94
|
logging.error("[broker] [%s]: %s", self.__broker, frame.body)
|
|
93
95
|
|
|
94
96
|
|
|
95
|
-
def setup_activemq(
|
|
97
|
+
def setup_activemq(
|
|
98
|
+
logger: "LoggerFunction"
|
|
99
|
+
) -> tuple[
|
|
100
|
+
Optional[list[stomp.Connection12]],
|
|
101
|
+
Optional[str],
|
|
102
|
+
Optional[str],
|
|
103
|
+
Optional[str],
|
|
104
|
+
Optional[bool]
|
|
105
|
+
]:
|
|
96
106
|
"""
|
|
97
107
|
Deliver messages to ActiveMQ
|
|
98
108
|
|
|
@@ -149,6 +159,8 @@ def setup_activemq(logger: "Callable"):
|
|
|
149
159
|
|
|
150
160
|
port = config_get_int("messaging-hermes", "port")
|
|
151
161
|
vhost = config_get("messaging-hermes", "broker_virtual_host", raise_exception=False)
|
|
162
|
+
username = None
|
|
163
|
+
password = None
|
|
152
164
|
if not use_ssl:
|
|
153
165
|
username = config_get("messaging-hermes", "username")
|
|
154
166
|
password = config_get("messaging-hermes", "password")
|
|
@@ -191,8 +203,14 @@ def setup_activemq(logger: "Callable"):
|
|
|
191
203
|
|
|
192
204
|
|
|
193
205
|
def deliver_to_activemq(
|
|
194
|
-
messages
|
|
195
|
-
|
|
206
|
+
messages: "Iterable[dict[str, Any]]",
|
|
207
|
+
conns: "Sequence[stomp.Connection12]",
|
|
208
|
+
destination: str,
|
|
209
|
+
username: str,
|
|
210
|
+
password: str,
|
|
211
|
+
use_ssl: bool,
|
|
212
|
+
logger: "LoggerFunction"
|
|
213
|
+
) -> list[str]:
|
|
196
214
|
"""
|
|
197
215
|
Deliver messages to ActiveMQ
|
|
198
216
|
|
|
@@ -315,7 +333,10 @@ def deliver_to_activemq(
|
|
|
315
333
|
return to_delete
|
|
316
334
|
|
|
317
335
|
|
|
318
|
-
def deliver_emails(
|
|
336
|
+
def deliver_emails(
|
|
337
|
+
messages: "Iterable[dict[str, Any]]",
|
|
338
|
+
logger: "LoggerFunction"
|
|
339
|
+
) -> list[str]:
|
|
319
340
|
"""
|
|
320
341
|
Sends emails
|
|
321
342
|
|
|
@@ -354,7 +375,11 @@ def deliver_emails(messages: list[dict], logger: "Callable") -> list:
|
|
|
354
375
|
return to_delete
|
|
355
376
|
|
|
356
377
|
|
|
357
|
-
def submit_to_elastic(
|
|
378
|
+
def submit_to_elastic(
|
|
379
|
+
messages: "Iterable[dict[str, Any]]",
|
|
380
|
+
endpoint: str,
|
|
381
|
+
logger: "LoggerFunction"
|
|
382
|
+
) -> int:
|
|
358
383
|
"""
|
|
359
384
|
Aggregate a list of message to ElasticSearch
|
|
360
385
|
|
|
@@ -365,23 +390,34 @@ def submit_to_elastic(messages: list[dict], endpoint: str, logger: "Callable") -
|
|
|
365
390
|
:returns: HTTP status code. 200 and 204 OK. Rest is failure.
|
|
366
391
|
"""
|
|
367
392
|
text = ""
|
|
393
|
+
elastic_username = config_get("hermes", "elastic_username",
|
|
394
|
+
raise_exception=False, default=None)
|
|
395
|
+
elastic_password = config_get("hermes", "elastic_password",
|
|
396
|
+
raise_exception=False, default=None)
|
|
397
|
+
auth = None
|
|
398
|
+
if elastic_username and elastic_password:
|
|
399
|
+
auth = HTTPBasicAuth(elastic_username, elastic_password)
|
|
400
|
+
|
|
368
401
|
for message in messages:
|
|
369
402
|
text += '{ "index":{ } }\n%s\n' % json.dumps(message, default=default)
|
|
370
403
|
res = requests.post(
|
|
371
|
-
endpoint, data=text, headers={"Content-Type": "application/json"}
|
|
404
|
+
endpoint, data=text, headers={"Content-Type": "application/json"}, auth=auth
|
|
372
405
|
)
|
|
373
406
|
return res.status_code
|
|
374
407
|
|
|
375
408
|
|
|
376
409
|
def aggregate_to_influx(
|
|
377
|
-
messages:
|
|
410
|
+
messages: "Iterable[dict[str, Any]]",
|
|
411
|
+
bin_size: int,
|
|
412
|
+
endpoint: str,
|
|
413
|
+
logger: "LoggerFunction"
|
|
378
414
|
) -> int:
|
|
379
415
|
"""
|
|
380
416
|
Aggregate a list of message using a certain bin_size
|
|
381
417
|
and submit them to a InfluxDB endpoint
|
|
382
418
|
|
|
383
419
|
:param messages: The list of messages.
|
|
384
|
-
:param bin_size: The size of the bins for the
|
|
420
|
+
:param bin_size: The size of the bins for the aggregation (e.g. 10m, 1h, etc.).
|
|
385
421
|
:param endpoint: The InfluxDB endpoint were to send the messages.
|
|
386
422
|
:param logger: The logger object.
|
|
387
423
|
|
|
@@ -625,7 +661,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
625
661
|
logger(
|
|
626
662
|
logging.ERROR,
|
|
627
663
|
"Failure to submit %s messages to elastic. Returned status: %s",
|
|
628
|
-
len(message_dict["
|
|
664
|
+
len(message_dict["elastic"]),
|
|
629
665
|
state,
|
|
630
666
|
)
|
|
631
667
|
except Exception as error:
|
|
@@ -655,10 +691,10 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
655
691
|
messages_sent = deliver_to_activemq(
|
|
656
692
|
messages=message_dict["activemq"],
|
|
657
693
|
conns=conns,
|
|
658
|
-
destination=destination,
|
|
659
|
-
username=username,
|
|
660
|
-
password=password,
|
|
661
|
-
use_ssl=use_ssl,
|
|
694
|
+
destination=destination, # type: ignore (argument could be None)
|
|
695
|
+
username=username, # type: ignore (argument could be None)
|
|
696
|
+
password=password, # type: ignore (argument could be None)
|
|
697
|
+
use_ssl=use_ssl, # type: ignore (argument could be None)
|
|
662
698
|
logger=logger,
|
|
663
699
|
)
|
|
664
700
|
logger(
|
|
@@ -689,7 +725,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
689
725
|
return must_sleep
|
|
690
726
|
|
|
691
727
|
|
|
692
|
-
def stop(signum:
|
|
728
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
693
729
|
"""
|
|
694
730
|
Graceful exit.
|
|
695
731
|
"""
|
rucio/daemons/judge/__init__.py
CHANGED
rucio/daemons/judge/cleaner.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");
|
|
@@ -24,29 +23,32 @@ from copy import deepcopy
|
|
|
24
23
|
from datetime import datetime, timedelta
|
|
25
24
|
from random import randint
|
|
26
25
|
from re import match
|
|
27
|
-
from typing import TYPE_CHECKING
|
|
26
|
+
from typing import TYPE_CHECKING, Optional
|
|
28
27
|
|
|
29
28
|
from sqlalchemy.exc import DatabaseError
|
|
30
29
|
|
|
31
30
|
import rucio.db.sqla.util
|
|
32
31
|
from rucio.common import exception
|
|
33
|
-
from rucio.common.exception import DatabaseException,
|
|
32
|
+
from rucio.common.exception import DatabaseException, RuleNotFound, UnsupportedOperation
|
|
34
33
|
from rucio.common.logging import setup_logging
|
|
35
34
|
from rucio.core.monitor import MetricManager
|
|
36
35
|
from rucio.core.rule import delete_rule, get_expired_rules
|
|
37
|
-
from rucio.daemons.common import run_daemon
|
|
36
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
37
|
+
from rucio.db.sqla.constants import ORACLE_CONNECTION_LOST_CONTACT_REGEX, ORACLE_RESOURCE_BUSY_REGEX
|
|
38
38
|
from rucio.db.sqla.util import get_db_time
|
|
39
39
|
|
|
40
40
|
if TYPE_CHECKING:
|
|
41
41
|
from types import FrameType
|
|
42
|
-
from typing import Optional
|
|
43
42
|
|
|
44
43
|
METRICS = MetricManager(module=__name__)
|
|
45
44
|
graceful_stop = threading.Event()
|
|
46
45
|
DAEMON_NAME = 'judge-cleaner'
|
|
47
46
|
|
|
48
47
|
|
|
49
|
-
def rule_cleaner(
|
|
48
|
+
def rule_cleaner(
|
|
49
|
+
once: bool = False,
|
|
50
|
+
sleep_time: int = 60
|
|
51
|
+
) -> None:
|
|
50
52
|
"""
|
|
51
53
|
Main loop to check for expired replication rules
|
|
52
54
|
"""
|
|
@@ -64,7 +66,11 @@ def rule_cleaner(once=False, sleep_time=60):
|
|
|
64
66
|
)
|
|
65
67
|
|
|
66
68
|
|
|
67
|
-
def run_once(
|
|
69
|
+
def run_once(
|
|
70
|
+
paused_rules: dict[str, datetime],
|
|
71
|
+
heartbeat_handler: HeartbeatHandler,
|
|
72
|
+
**_kwargs
|
|
73
|
+
) -> None:
|
|
68
74
|
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
69
75
|
|
|
70
76
|
start = time.time()
|
|
@@ -97,14 +103,14 @@ def run_once(paused_rules, heartbeat_handler, **_kwargs):
|
|
|
97
103
|
delete_rule(rule_id=rule_id, nowait=True)
|
|
98
104
|
logger(logging.DEBUG, 'deletion of %s took %f' % (rule_id, time.time() - start))
|
|
99
105
|
except (DatabaseException, DatabaseError, UnsupportedOperation) as e:
|
|
100
|
-
if match(
|
|
101
|
-
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(600, 2400))
|
|
106
|
+
if match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])):
|
|
107
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(600, 2400)) # noqa: S311
|
|
102
108
|
METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
|
|
103
109
|
logger(logging.WARNING, 'Locks detected for %s' % rule_id)
|
|
104
110
|
elif match('.*QueuePool.*', str(e.args[0])):
|
|
105
111
|
logger(logging.WARNING, 'DatabaseException', exc_info=True)
|
|
106
112
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
107
|
-
elif match(
|
|
113
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(e.args[0])):
|
|
108
114
|
logger(logging.WARNING, 'DatabaseException', exc_info=True)
|
|
109
115
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
110
116
|
else:
|
|
@@ -114,14 +120,18 @@ def run_once(paused_rules, heartbeat_handler, **_kwargs):
|
|
|
114
120
|
pass
|
|
115
121
|
|
|
116
122
|
|
|
117
|
-
def stop(signum:
|
|
123
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
118
124
|
"""
|
|
119
125
|
Graceful exit.
|
|
120
126
|
"""
|
|
121
127
|
graceful_stop.set()
|
|
122
128
|
|
|
123
129
|
|
|
124
|
-
def run(
|
|
130
|
+
def run(
|
|
131
|
+
once: bool = False,
|
|
132
|
+
threads: int = 1,
|
|
133
|
+
sleep_time: int = 60
|
|
134
|
+
) -> None:
|
|
125
135
|
"""
|
|
126
136
|
Starts up the Judge-Clean threads.
|
|
127
137
|
"""
|
|
@@ -141,9 +151,9 @@ def run(once=False, threads=1, sleep_time=60):
|
|
|
141
151
|
rule_cleaner(once)
|
|
142
152
|
else:
|
|
143
153
|
logging.info('Cleaner starting %s threads' % str(threads))
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
[t.start() for t in
|
|
154
|
+
thread_list = [threading.Thread(target=rule_cleaner, kwargs={'once': once,
|
|
155
|
+
'sleep_time': sleep_time}) for i in range(0, threads)]
|
|
156
|
+
[t.start() for t in thread_list]
|
|
147
157
|
# Interruptible joins require a timeout.
|
|
148
|
-
while
|
|
149
|
-
[t.join(timeout=3.14) for t in
|
|
158
|
+
while thread_list[0].is_alive():
|
|
159
|
+
[t.join(timeout=3.14) for t in thread_list]
|
rucio/daemons/judge/evaluator.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");
|
|
@@ -25,7 +24,7 @@ import traceback
|
|
|
25
24
|
from datetime import datetime, timedelta
|
|
26
25
|
from random import randint
|
|
27
26
|
from re import match
|
|
28
|
-
from typing import TYPE_CHECKING
|
|
27
|
+
from typing import TYPE_CHECKING, Optional
|
|
29
28
|
|
|
30
29
|
from sqlalchemy.exc import DatabaseError
|
|
31
30
|
from sqlalchemy.orm.exc import FlushError
|
|
@@ -35,19 +34,23 @@ from rucio.common.exception import DatabaseException, DataIdentifierNotFound, Re
|
|
|
35
34
|
from rucio.common.logging import setup_logging
|
|
36
35
|
from rucio.common.types import InternalScope
|
|
37
36
|
from rucio.core.monitor import MetricManager
|
|
38
|
-
from rucio.core.rule import
|
|
39
|
-
from rucio.daemons.common import run_daemon
|
|
37
|
+
from rucio.core.rule import delete_updated_did, get_updated_dids, re_evaluate_did
|
|
38
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
39
|
+
from rucio.db.sqla.constants import ORACLE_CONNECTION_LOST_CONTACT_REGEX, ORACLE_RESOURCE_BUSY_REGEX, ORACLE_UNIQUE_CONSTRAINT_VIOLATED_REGEX
|
|
40
40
|
|
|
41
41
|
if TYPE_CHECKING:
|
|
42
42
|
from types import FrameType
|
|
43
|
-
from typing import Optional
|
|
44
43
|
|
|
45
44
|
METRICS = MetricManager(module=__name__)
|
|
46
45
|
graceful_stop = threading.Event()
|
|
47
46
|
DAEMON_NAME = 'judge-evaluator'
|
|
48
47
|
|
|
49
48
|
|
|
50
|
-
def re_evaluator(
|
|
49
|
+
def re_evaluator(
|
|
50
|
+
once: bool = False,
|
|
51
|
+
sleep_time: int = 30,
|
|
52
|
+
did_limit: int = 100
|
|
53
|
+
) -> None:
|
|
51
54
|
"""
|
|
52
55
|
Main loop to check the re-evaluation of dids.
|
|
53
56
|
"""
|
|
@@ -67,7 +70,12 @@ def re_evaluator(once=False, sleep_time=30, did_limit=100):
|
|
|
67
70
|
)
|
|
68
71
|
|
|
69
72
|
|
|
70
|
-
def run_once(
|
|
73
|
+
def run_once(
|
|
74
|
+
paused_dids: dict[tuple[str, str], datetime],
|
|
75
|
+
did_limit: int,
|
|
76
|
+
heartbeat_handler: HeartbeatHandler,
|
|
77
|
+
**_kwargs
|
|
78
|
+
) -> None:
|
|
71
79
|
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
72
80
|
|
|
73
81
|
# heartbeat
|
|
@@ -121,14 +129,14 @@ def run_once(paused_dids, did_limit, heartbeat_handler, **_kwargs):
|
|
|
121
129
|
except DataIdentifierNotFound:
|
|
122
130
|
delete_updated_did(id_=did.id)
|
|
123
131
|
except (DatabaseException, DatabaseError) as e:
|
|
124
|
-
if match(
|
|
125
|
-
paused_dids[(did.scope.internal, did.name)] = datetime.utcnow() + timedelta(seconds=randint(60, 600))
|
|
132
|
+
if match(ORACLE_UNIQUE_CONSTRAINT_VIOLATED_REGEX, str(e.args[0])) or match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])):
|
|
133
|
+
paused_dids[(did.scope.internal, did.name)] = datetime.utcnow() + timedelta(seconds=randint(60, 600)) # noqa: S311
|
|
126
134
|
logger(logging.WARNING, 'Locks detected for %s:%s', did.scope, did.name)
|
|
127
135
|
METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
|
|
128
136
|
elif match('.*QueuePool.*', str(e.args[0])):
|
|
129
137
|
logger(logging.WARNING, traceback.format_exc())
|
|
130
138
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
131
|
-
elif match(
|
|
139
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(e.args[0])):
|
|
132
140
|
logger(logging.WARNING, traceback.format_exc())
|
|
133
141
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
134
142
|
else:
|
|
@@ -142,7 +150,7 @@ def run_once(paused_dids, did_limit, heartbeat_handler, **_kwargs):
|
|
|
142
150
|
logger(logging.WARNING, 'Flush error for %s:%s', did.scope, did.name)
|
|
143
151
|
|
|
144
152
|
|
|
145
|
-
def stop(signum:
|
|
153
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
146
154
|
"""
|
|
147
155
|
Graceful exit.
|
|
148
156
|
"""
|
|
@@ -150,7 +158,12 @@ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) ->
|
|
|
150
158
|
graceful_stop.set()
|
|
151
159
|
|
|
152
160
|
|
|
153
|
-
def run(
|
|
161
|
+
def run(
|
|
162
|
+
once: bool = False,
|
|
163
|
+
threads: int = 1,
|
|
164
|
+
sleep_time: int = 30,
|
|
165
|
+
did_limit: int = 100
|
|
166
|
+
) -> None:
|
|
154
167
|
"""
|
|
155
168
|
Starts up the Judge-Eval threads.
|
|
156
169
|
"""
|
|
@@ -163,10 +176,10 @@ def run(once=False, threads=1, sleep_time=30, did_limit=100):
|
|
|
163
176
|
re_evaluator(once=once, did_limit=did_limit)
|
|
164
177
|
else:
|
|
165
178
|
logging.info('Evaluator starting %s threads' % str(threads))
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
[t.start() for t in
|
|
179
|
+
thread_list = [threading.Thread(target=re_evaluator, kwargs={'once': once,
|
|
180
|
+
'sleep_time': sleep_time,
|
|
181
|
+
'did_limit': did_limit}) for i in range(0, threads)]
|
|
182
|
+
[t.start() for t in thread_list]
|
|
170
183
|
# Interruptible joins require a timeout.
|
|
171
|
-
while
|
|
172
|
-
[t.join(timeout=3.14) for t in
|
|
184
|
+
while thread_list[0].is_alive():
|
|
185
|
+
[t.join(timeout=3.14) for t in thread_list]
|
rucio/daemons/judge/injector.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");
|
|
@@ -24,28 +23,30 @@ from copy import deepcopy
|
|
|
24
23
|
from datetime import datetime, timedelta
|
|
25
24
|
from random import randint
|
|
26
25
|
from re import match
|
|
27
|
-
from typing import TYPE_CHECKING
|
|
26
|
+
from typing import TYPE_CHECKING, Optional
|
|
28
27
|
|
|
29
28
|
from sqlalchemy.exc import DatabaseError
|
|
30
29
|
|
|
31
30
|
import rucio.db.sqla.util
|
|
32
|
-
from rucio.common.exception import
|
|
33
|
-
ReplicationRuleCreationTemporaryFailed, InsufficientAccountLimit)
|
|
31
|
+
from rucio.common.exception import DatabaseException, InsufficientAccountLimit, ReplicationRuleCreationTemporaryFailed, RSEWriteBlocked, RuleNotFound
|
|
34
32
|
from rucio.common.logging import setup_logging
|
|
35
33
|
from rucio.core.monitor import MetricManager
|
|
36
|
-
from rucio.core.rule import
|
|
37
|
-
from rucio.daemons.common import run_daemon
|
|
34
|
+
from rucio.core.rule import get_injected_rules, inject_rule, update_rule
|
|
35
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
36
|
+
from rucio.db.sqla.constants import ORACLE_CONNECTION_LOST_CONTACT_REGEX, ORACLE_RESOURCE_BUSY_REGEX
|
|
38
37
|
|
|
39
38
|
if TYPE_CHECKING:
|
|
40
39
|
from types import FrameType
|
|
41
|
-
from typing import Optional
|
|
42
40
|
|
|
43
41
|
METRICS = MetricManager(module=__name__)
|
|
44
42
|
graceful_stop = threading.Event()
|
|
45
43
|
DAEMON_NAME = 'judge-injector'
|
|
46
44
|
|
|
47
45
|
|
|
48
|
-
def rule_injector(
|
|
46
|
+
def rule_injector(
|
|
47
|
+
once: bool = False,
|
|
48
|
+
sleep_time: int = 60
|
|
49
|
+
) -> None:
|
|
49
50
|
"""
|
|
50
51
|
Main loop to check for asynchronous creation of replication rules
|
|
51
52
|
"""
|
|
@@ -63,7 +64,11 @@ def rule_injector(once=False, sleep_time=60):
|
|
|
63
64
|
)
|
|
64
65
|
|
|
65
66
|
|
|
66
|
-
def run_once(
|
|
67
|
+
def run_once(
|
|
68
|
+
paused_rules: dict[str, datetime],
|
|
69
|
+
heartbeat_handler: HeartbeatHandler,
|
|
70
|
+
**_kwargs
|
|
71
|
+
) -> None:
|
|
67
72
|
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
68
73
|
|
|
69
74
|
start = time.time()
|
|
@@ -84,9 +89,8 @@ def run_once(paused_rules, heartbeat_handler, **_kwargs):
|
|
|
84
89
|
logger(logging.DEBUG, 'did not get any work (paused_rules=%s)' % str(len(paused_rules)))
|
|
85
90
|
return
|
|
86
91
|
|
|
87
|
-
for
|
|
92
|
+
for rule_id in rules:
|
|
88
93
|
_, _, logger = heartbeat_handler.live()
|
|
89
|
-
rule_id = rule[0]
|
|
90
94
|
logger(logging.INFO, 'Injecting rule %s' % rule_id)
|
|
91
95
|
if graceful_stop.is_set():
|
|
92
96
|
break
|
|
@@ -95,25 +99,25 @@ def run_once(paused_rules, heartbeat_handler, **_kwargs):
|
|
|
95
99
|
inject_rule(rule_id=rule_id, logger=logger)
|
|
96
100
|
logger(logging.DEBUG, 'injection of %s took %f' % (rule_id, time.time() - start))
|
|
97
101
|
except (DatabaseException, DatabaseError) as e:
|
|
98
|
-
if match(
|
|
99
|
-
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600))
|
|
102
|
+
if match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])):
|
|
103
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600)) # noqa: S311
|
|
100
104
|
METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
|
|
101
105
|
logger(logging.WARNING, 'Locks detected for %s' % rule_id)
|
|
102
106
|
elif match('.*QueuePool.*', str(e.args[0])):
|
|
103
107
|
logger(logging.WARNING, 'DatabaseException', exc_info=True)
|
|
104
108
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
105
|
-
elif match(
|
|
109
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(e.args[0])):
|
|
106
110
|
logger(logging.WARNING, 'DatabaseException', exc_info=True)
|
|
107
111
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
108
112
|
else:
|
|
109
113
|
logger(logging.ERROR, 'DatabaseException', exc_info=True)
|
|
110
114
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
111
115
|
except (RSEWriteBlocked) as e:
|
|
112
|
-
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600))
|
|
116
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600)) # noqa: S311
|
|
113
117
|
logger(logging.WARNING, 'RSEWriteBlocked for rule %s' % rule_id)
|
|
114
118
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
115
119
|
except ReplicationRuleCreationTemporaryFailed as e:
|
|
116
|
-
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600))
|
|
120
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600)) # noqa: S311
|
|
117
121
|
logger(logging.WARNING, 'ReplicationRuleCreationTemporaryFailed for rule %s' % rule_id)
|
|
118
122
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
119
123
|
except RuleNotFound:
|
|
@@ -125,7 +129,7 @@ def run_once(paused_rules, heartbeat_handler, **_kwargs):
|
|
|
125
129
|
update_rule(rule_id=rule_id, options={'state': 'SUSPENDED'})
|
|
126
130
|
|
|
127
131
|
|
|
128
|
-
def stop(signum:
|
|
132
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
129
133
|
"""
|
|
130
134
|
Graceful exit.
|
|
131
135
|
"""
|
|
@@ -133,7 +137,11 @@ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) ->
|
|
|
133
137
|
graceful_stop.set()
|
|
134
138
|
|
|
135
139
|
|
|
136
|
-
def run(
|
|
140
|
+
def run(
|
|
141
|
+
once: bool = False,
|
|
142
|
+
threads: int = 1,
|
|
143
|
+
sleep_time: int = 60
|
|
144
|
+
) -> None:
|
|
137
145
|
"""
|
|
138
146
|
Starts up the Judge-Injector threads.
|
|
139
147
|
"""
|
|
@@ -146,9 +154,9 @@ def run(once=False, threads=1, sleep_time=60):
|
|
|
146
154
|
rule_injector(once)
|
|
147
155
|
else:
|
|
148
156
|
logging.info('Injector starting %s threads' % str(threads))
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
[t.start() for t in
|
|
157
|
+
thread_list = [threading.Thread(target=rule_injector, kwargs={'once': once,
|
|
158
|
+
'sleep_time': sleep_time}) for i in range(0, threads)]
|
|
159
|
+
[t.start() for t in thread_list]
|
|
152
160
|
# Interruptible joins require a timeout.
|
|
153
|
-
while
|
|
154
|
-
[t.join(timeout=3.14) for t in
|
|
161
|
+
while thread_list[0].is_alive():
|
|
162
|
+
[t.join(timeout=3.14) for t in thread_list]
|
rucio/daemons/judge/repairer.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");
|
|
@@ -25,7 +24,7 @@ from copy import deepcopy
|
|
|
25
24
|
from datetime import datetime, timedelta
|
|
26
25
|
from random import randint
|
|
27
26
|
from re import match
|
|
28
|
-
from typing import TYPE_CHECKING
|
|
27
|
+
from typing import TYPE_CHECKING, Optional
|
|
29
28
|
|
|
30
29
|
from sqlalchemy.exc import DatabaseError
|
|
31
30
|
|
|
@@ -34,19 +33,22 @@ from rucio.common import exception
|
|
|
34
33
|
from rucio.common.exception import DatabaseException
|
|
35
34
|
from rucio.common.logging import setup_logging
|
|
36
35
|
from rucio.core.monitor import MetricManager
|
|
37
|
-
from rucio.core.rule import
|
|
38
|
-
from rucio.daemons.common import run_daemon
|
|
36
|
+
from rucio.core.rule import get_stuck_rules, repair_rule
|
|
37
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
38
|
+
from rucio.db.sqla.constants import ORACLE_CONNECTION_LOST_CONTACT_REGEX, ORACLE_RESOURCE_BUSY_REGEX
|
|
39
39
|
|
|
40
40
|
if TYPE_CHECKING:
|
|
41
41
|
from types import FrameType
|
|
42
|
-
from typing import Optional
|
|
43
42
|
|
|
44
43
|
METRICS = MetricManager(module=__name__)
|
|
45
44
|
graceful_stop = threading.Event()
|
|
46
45
|
DAEMON_NAME = 'judge-repairer'
|
|
47
46
|
|
|
48
47
|
|
|
49
|
-
def rule_repairer(
|
|
48
|
+
def rule_repairer(
|
|
49
|
+
once: bool = False,
|
|
50
|
+
sleep_time: int = 60
|
|
51
|
+
) -> None:
|
|
50
52
|
"""
|
|
51
53
|
Main loop to check for STUCK replication rules
|
|
52
54
|
"""
|
|
@@ -65,7 +67,12 @@ def rule_repairer(once=False, sleep_time=60):
|
|
|
65
67
|
)
|
|
66
68
|
|
|
67
69
|
|
|
68
|
-
def run_once(
|
|
70
|
+
def run_once(
|
|
71
|
+
paused_rules: dict[str, datetime],
|
|
72
|
+
delta: int,
|
|
73
|
+
heartbeat_handler: HeartbeatHandler,
|
|
74
|
+
**_kwargs
|
|
75
|
+
) -> None:
|
|
69
76
|
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
70
77
|
|
|
71
78
|
start = time.time()
|
|
@@ -91,7 +98,6 @@ def run_once(paused_rules, delta, heartbeat_handler, **_kwargs):
|
|
|
91
98
|
|
|
92
99
|
for rule_id in rules:
|
|
93
100
|
_, _, logger = heartbeat_handler.live()
|
|
94
|
-
rule_id = rule_id[0]
|
|
95
101
|
logger(logging.INFO, 'Repairing rule %s' % (rule_id))
|
|
96
102
|
if graceful_stop.is_set():
|
|
97
103
|
break
|
|
@@ -100,14 +106,14 @@ def run_once(paused_rules, delta, heartbeat_handler, **_kwargs):
|
|
|
100
106
|
repair_rule(rule_id=rule_id)
|
|
101
107
|
logger(logging.DEBUG, 'repairing of %s took %f' % (rule_id, time.time() - start))
|
|
102
108
|
except (DatabaseException, DatabaseError) as e:
|
|
103
|
-
if match(
|
|
104
|
-
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(600, 2400))
|
|
109
|
+
if match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])):
|
|
110
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(600, 2400)) # noqa: S311
|
|
105
111
|
logger(logging.WARNING, 'Locks detected for %s' % (rule_id))
|
|
106
112
|
METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
|
|
107
113
|
elif match('.*QueuePool.*', str(e.args[0])):
|
|
108
114
|
logger(logging.WARNING, traceback.format_exc())
|
|
109
115
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
110
|
-
elif match(
|
|
116
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(e.args[0])):
|
|
111
117
|
logger(logging.WARNING, traceback.format_exc())
|
|
112
118
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
113
119
|
else:
|
|
@@ -115,7 +121,7 @@ def run_once(paused_rules, delta, heartbeat_handler, **_kwargs):
|
|
|
115
121
|
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
116
122
|
|
|
117
123
|
|
|
118
|
-
def stop(signum:
|
|
124
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
119
125
|
"""
|
|
120
126
|
Graceful exit.
|
|
121
127
|
"""
|
|
@@ -123,7 +129,11 @@ def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) ->
|
|
|
123
129
|
graceful_stop.set()
|
|
124
130
|
|
|
125
131
|
|
|
126
|
-
def run(
|
|
132
|
+
def run(
|
|
133
|
+
once: bool = False,
|
|
134
|
+
threads: int = 1,
|
|
135
|
+
sleep_time: int = 60
|
|
136
|
+
) -> None:
|
|
127
137
|
"""
|
|
128
138
|
Starts up the Judge-Repairer threads.
|
|
129
139
|
"""
|
|
@@ -136,9 +146,9 @@ def run(once=False, threads=1, sleep_time=60):
|
|
|
136
146
|
rule_repairer(once)
|
|
137
147
|
else:
|
|
138
148
|
logging.info('Repairer starting %s threads' % str(threads))
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
[t.start() for t in
|
|
149
|
+
thread_list = [threading.Thread(target=rule_repairer, kwargs={'once': once,
|
|
150
|
+
'sleep_time': sleep_time}) for i in range(0, threads)]
|
|
151
|
+
[t.start() for t in thread_list]
|
|
142
152
|
# Interruptible joins require a timeout.
|
|
143
|
-
while
|
|
144
|
-
[t.join(timeout=3.14) for t in
|
|
153
|
+
while thread_list[0].is_alive():
|
|
154
|
+
[t.join(timeout=3.14) for t in thread_list]
|