rucio 37.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/__init__.py +17 -0
- rucio/alembicrevision.py +15 -0
- rucio/cli/__init__.py +14 -0
- rucio/cli/account.py +216 -0
- rucio/cli/bin_legacy/__init__.py +13 -0
- rucio/cli/bin_legacy/rucio.py +2825 -0
- rucio/cli/bin_legacy/rucio_admin.py +2500 -0
- rucio/cli/command.py +272 -0
- rucio/cli/config.py +72 -0
- rucio/cli/did.py +191 -0
- rucio/cli/download.py +128 -0
- rucio/cli/lifetime_exception.py +33 -0
- rucio/cli/replica.py +162 -0
- rucio/cli/rse.py +293 -0
- rucio/cli/rule.py +158 -0
- rucio/cli/scope.py +40 -0
- rucio/cli/subscription.py +73 -0
- rucio/cli/upload.py +60 -0
- rucio/cli/utils.py +226 -0
- rucio/client/__init__.py +15 -0
- rucio/client/accountclient.py +432 -0
- rucio/client/accountlimitclient.py +183 -0
- rucio/client/baseclient.py +983 -0
- rucio/client/client.py +120 -0
- rucio/client/configclient.py +126 -0
- rucio/client/credentialclient.py +59 -0
- rucio/client/didclient.py +868 -0
- rucio/client/diracclient.py +56 -0
- rucio/client/downloadclient.py +1783 -0
- rucio/client/exportclient.py +44 -0
- rucio/client/fileclient.py +50 -0
- rucio/client/importclient.py +42 -0
- rucio/client/lifetimeclient.py +90 -0
- rucio/client/lockclient.py +109 -0
- rucio/client/metaconventionsclient.py +140 -0
- rucio/client/pingclient.py +44 -0
- rucio/client/replicaclient.py +452 -0
- rucio/client/requestclient.py +125 -0
- rucio/client/richclient.py +317 -0
- rucio/client/rseclient.py +746 -0
- rucio/client/ruleclient.py +294 -0
- rucio/client/scopeclient.py +90 -0
- rucio/client/subscriptionclient.py +173 -0
- rucio/client/touchclient.py +82 -0
- rucio/client/uploadclient.py +969 -0
- rucio/common/__init__.py +13 -0
- rucio/common/bittorrent.py +234 -0
- rucio/common/cache.py +111 -0
- rucio/common/checksum.py +168 -0
- rucio/common/client.py +122 -0
- rucio/common/config.py +788 -0
- rucio/common/constants.py +217 -0
- rucio/common/constraints.py +17 -0
- rucio/common/didtype.py +237 -0
- rucio/common/dumper/__init__.py +342 -0
- rucio/common/dumper/consistency.py +497 -0
- rucio/common/dumper/data_models.py +362 -0
- rucio/common/dumper/path_parsing.py +75 -0
- rucio/common/exception.py +1208 -0
- rucio/common/extra.py +31 -0
- rucio/common/logging.py +420 -0
- rucio/common/pcache.py +1409 -0
- rucio/common/plugins.py +185 -0
- rucio/common/policy.py +93 -0
- rucio/common/schema/__init__.py +200 -0
- rucio/common/schema/generic.py +416 -0
- rucio/common/schema/generic_multi_vo.py +395 -0
- rucio/common/stomp_utils.py +423 -0
- rucio/common/stopwatch.py +55 -0
- rucio/common/test_rucio_server.py +154 -0
- rucio/common/types.py +483 -0
- rucio/common/utils.py +1688 -0
- rucio/core/__init__.py +13 -0
- rucio/core/account.py +496 -0
- rucio/core/account_counter.py +236 -0
- rucio/core/account_limit.py +425 -0
- rucio/core/authentication.py +620 -0
- rucio/core/config.py +437 -0
- rucio/core/credential.py +224 -0
- rucio/core/did.py +3004 -0
- rucio/core/did_meta_plugins/__init__.py +252 -0
- rucio/core/did_meta_plugins/did_column_meta.py +331 -0
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +165 -0
- rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
- rucio/core/did_meta_plugins/filter_engine.py +672 -0
- rucio/core/did_meta_plugins/json_meta.py +240 -0
- rucio/core/did_meta_plugins/mongo_meta.py +229 -0
- rucio/core/did_meta_plugins/postgres_meta.py +352 -0
- rucio/core/dirac.py +237 -0
- rucio/core/distance.py +187 -0
- rucio/core/exporter.py +59 -0
- rucio/core/heartbeat.py +363 -0
- rucio/core/identity.py +301 -0
- rucio/core/importer.py +260 -0
- rucio/core/lifetime_exception.py +377 -0
- rucio/core/lock.py +577 -0
- rucio/core/message.py +288 -0
- rucio/core/meta_conventions.py +203 -0
- rucio/core/monitor.py +448 -0
- rucio/core/naming_convention.py +195 -0
- rucio/core/nongrid_trace.py +136 -0
- rucio/core/oidc.py +1463 -0
- rucio/core/permission/__init__.py +161 -0
- rucio/core/permission/generic.py +1124 -0
- rucio/core/permission/generic_multi_vo.py +1144 -0
- rucio/core/quarantined_replica.py +224 -0
- rucio/core/replica.py +4483 -0
- rucio/core/replica_sorter.py +362 -0
- rucio/core/request.py +3091 -0
- rucio/core/rse.py +2079 -0
- rucio/core/rse_counter.py +185 -0
- rucio/core/rse_expression_parser.py +459 -0
- rucio/core/rse_selector.py +304 -0
- rucio/core/rule.py +4484 -0
- rucio/core/rule_grouping.py +1620 -0
- rucio/core/scope.py +181 -0
- rucio/core/subscription.py +362 -0
- rucio/core/topology.py +490 -0
- rucio/core/trace.py +375 -0
- rucio/core/transfer.py +1531 -0
- rucio/core/vo.py +169 -0
- rucio/core/volatile_replica.py +151 -0
- rucio/daemons/__init__.py +13 -0
- rucio/daemons/abacus/__init__.py +13 -0
- rucio/daemons/abacus/account.py +116 -0
- rucio/daemons/abacus/collection_replica.py +124 -0
- rucio/daemons/abacus/rse.py +117 -0
- rucio/daemons/atropos/__init__.py +13 -0
- rucio/daemons/atropos/atropos.py +242 -0
- rucio/daemons/auditor/__init__.py +289 -0
- rucio/daemons/auditor/hdfs.py +97 -0
- rucio/daemons/auditor/srmdumps.py +355 -0
- rucio/daemons/automatix/__init__.py +13 -0
- rucio/daemons/automatix/automatix.py +304 -0
- rucio/daemons/badreplicas/__init__.py +13 -0
- rucio/daemons/badreplicas/minos.py +322 -0
- rucio/daemons/badreplicas/minos_temporary_expiration.py +171 -0
- rucio/daemons/badreplicas/necromancer.py +196 -0
- rucio/daemons/bb8/__init__.py +13 -0
- rucio/daemons/bb8/bb8.py +353 -0
- rucio/daemons/bb8/common.py +759 -0
- rucio/daemons/bb8/nuclei_background_rebalance.py +153 -0
- rucio/daemons/bb8/t2_background_rebalance.py +153 -0
- rucio/daemons/cache/__init__.py +13 -0
- rucio/daemons/cache/consumer.py +133 -0
- rucio/daemons/common.py +405 -0
- rucio/daemons/conveyor/__init__.py +13 -0
- rucio/daemons/conveyor/common.py +562 -0
- rucio/daemons/conveyor/finisher.py +529 -0
- rucio/daemons/conveyor/poller.py +394 -0
- rucio/daemons/conveyor/preparer.py +205 -0
- rucio/daemons/conveyor/receiver.py +179 -0
- rucio/daemons/conveyor/stager.py +133 -0
- rucio/daemons/conveyor/submitter.py +403 -0
- rucio/daemons/conveyor/throttler.py +532 -0
- rucio/daemons/follower/__init__.py +13 -0
- rucio/daemons/follower/follower.py +101 -0
- rucio/daemons/hermes/__init__.py +13 -0
- rucio/daemons/hermes/hermes.py +534 -0
- rucio/daemons/judge/__init__.py +13 -0
- rucio/daemons/judge/cleaner.py +159 -0
- rucio/daemons/judge/evaluator.py +185 -0
- rucio/daemons/judge/injector.py +162 -0
- rucio/daemons/judge/repairer.py +154 -0
- rucio/daemons/oauthmanager/__init__.py +13 -0
- rucio/daemons/oauthmanager/oauthmanager.py +198 -0
- rucio/daemons/reaper/__init__.py +13 -0
- rucio/daemons/reaper/dark_reaper.py +282 -0
- rucio/daemons/reaper/reaper.py +739 -0
- rucio/daemons/replicarecoverer/__init__.py +13 -0
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +626 -0
- rucio/daemons/rsedecommissioner/__init__.py +13 -0
- rucio/daemons/rsedecommissioner/config.py +81 -0
- rucio/daemons/rsedecommissioner/profiles/__init__.py +24 -0
- rucio/daemons/rsedecommissioner/profiles/atlas.py +60 -0
- rucio/daemons/rsedecommissioner/profiles/generic.py +452 -0
- rucio/daemons/rsedecommissioner/profiles/types.py +93 -0
- rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
- rucio/daemons/storage/__init__.py +13 -0
- rucio/daemons/storage/consistency/__init__.py +13 -0
- rucio/daemons/storage/consistency/actions.py +848 -0
- rucio/daemons/tracer/__init__.py +13 -0
- rucio/daemons/tracer/kronos.py +511 -0
- rucio/daemons/transmogrifier/__init__.py +13 -0
- rucio/daemons/transmogrifier/transmogrifier.py +762 -0
- rucio/daemons/undertaker/__init__.py +13 -0
- rucio/daemons/undertaker/undertaker.py +137 -0
- rucio/db/__init__.py +13 -0
- rucio/db/sqla/__init__.py +52 -0
- rucio/db/sqla/constants.py +206 -0
- rucio/db/sqla/migrate_repo/__init__.py +13 -0
- rucio/db/sqla/migrate_repo/env.py +110 -0
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +70 -0
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +91 -0
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +76 -0
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +43 -0
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +50 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +68 -0
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +40 -0
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +45 -0
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +60 -0
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +40 -0
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +140 -0
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +73 -0
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +74 -0
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +43 -0
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +50 -0
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +134 -0
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +64 -0
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +39 -0
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +64 -0
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +51 -0
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +41 -0
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +43 -0
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +44 -0
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +53 -0
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +38 -0
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +47 -0
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +57 -0
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +69 -0
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +42 -0
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +46 -0
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +40 -0
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +67 -0
- rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +44 -0
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +77 -0
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +60 -0
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +72 -0
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +42 -0
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +65 -0
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +133 -0
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +76 -0
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +60 -0
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +44 -0
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +64 -0
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +40 -0
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +43 -0
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +44 -0
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +78 -0
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +41 -0
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +44 -0
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +49 -0
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +40 -0
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +63 -0
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +55 -0
- rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +45 -0
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +47 -0
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +58 -0
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +45 -0
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +106 -0
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +55 -0
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +50 -0
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +43 -0
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +41 -0
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +91 -0
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +72 -0
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +49 -0
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +43 -0
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +53 -0
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +45 -0
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +68 -0
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +45 -0
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +94 -0
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +54 -0
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +72 -0
- rucio/db/sqla/migrate_repo/versions/a08fa8de1545_transfer_stats_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +76 -0
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +47 -0
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +121 -0
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +59 -0
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +52 -0
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +54 -0
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +64 -0
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +49 -0
- rucio/db/sqla/migrate_repo/versions/b0070f3695c8_add_deletedidmeta_table.py +57 -0
- rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +43 -0
- rucio/db/sqla/migrate_repo/versions/b5493606bbf5_fix_primary_key_for_subscription_history.py +41 -0
- rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +91 -0
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +40 -0
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +143 -0
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +76 -0
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +50 -0
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +72 -0
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +43 -0
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +65 -0
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +47 -0
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +146 -0
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +104 -0
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +44 -0
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +43 -0
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +103 -0
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +49 -0
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +104 -0
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +29 -0
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +74 -0
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +43 -0
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +37 -0
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +43 -0
- rucio/db/sqla/models.py +1743 -0
- rucio/db/sqla/sautils.py +55 -0
- rucio/db/sqla/session.py +529 -0
- rucio/db/sqla/types.py +206 -0
- rucio/db/sqla/util.py +543 -0
- rucio/gateway/__init__.py +13 -0
- rucio/gateway/account.py +345 -0
- rucio/gateway/account_limit.py +363 -0
- rucio/gateway/authentication.py +381 -0
- rucio/gateway/config.py +227 -0
- rucio/gateway/credential.py +70 -0
- rucio/gateway/did.py +987 -0
- rucio/gateway/dirac.py +83 -0
- rucio/gateway/exporter.py +60 -0
- rucio/gateway/heartbeat.py +76 -0
- rucio/gateway/identity.py +189 -0
- rucio/gateway/importer.py +46 -0
- rucio/gateway/lifetime_exception.py +121 -0
- rucio/gateway/lock.py +153 -0
- rucio/gateway/meta_conventions.py +98 -0
- rucio/gateway/permission.py +74 -0
- rucio/gateway/quarantined_replica.py +79 -0
- rucio/gateway/replica.py +538 -0
- rucio/gateway/request.py +330 -0
- rucio/gateway/rse.py +632 -0
- rucio/gateway/rule.py +437 -0
- rucio/gateway/scope.py +100 -0
- rucio/gateway/subscription.py +280 -0
- rucio/gateway/vo.py +126 -0
- rucio/rse/__init__.py +96 -0
- rucio/rse/protocols/__init__.py +13 -0
- rucio/rse/protocols/bittorrent.py +194 -0
- rucio/rse/protocols/cache.py +111 -0
- rucio/rse/protocols/dummy.py +100 -0
- rucio/rse/protocols/gfal.py +708 -0
- rucio/rse/protocols/globus.py +243 -0
- rucio/rse/protocols/http_cache.py +82 -0
- rucio/rse/protocols/mock.py +123 -0
- rucio/rse/protocols/ngarc.py +209 -0
- rucio/rse/protocols/posix.py +250 -0
- rucio/rse/protocols/protocol.py +361 -0
- rucio/rse/protocols/rclone.py +365 -0
- rucio/rse/protocols/rfio.py +145 -0
- rucio/rse/protocols/srm.py +338 -0
- rucio/rse/protocols/ssh.py +414 -0
- rucio/rse/protocols/storm.py +195 -0
- rucio/rse/protocols/webdav.py +594 -0
- rucio/rse/protocols/xrootd.py +302 -0
- rucio/rse/rsemanager.py +881 -0
- rucio/rse/translation.py +260 -0
- rucio/tests/__init__.py +13 -0
- rucio/tests/common.py +280 -0
- rucio/tests/common_server.py +149 -0
- rucio/transfertool/__init__.py +13 -0
- rucio/transfertool/bittorrent.py +200 -0
- rucio/transfertool/bittorrent_driver.py +50 -0
- rucio/transfertool/bittorrent_driver_qbittorrent.py +134 -0
- rucio/transfertool/fts3.py +1600 -0
- rucio/transfertool/fts3_plugins.py +152 -0
- rucio/transfertool/globus.py +201 -0
- rucio/transfertool/globus_library.py +181 -0
- rucio/transfertool/mock.py +89 -0
- rucio/transfertool/transfertool.py +221 -0
- rucio/vcsversion.py +11 -0
- rucio/version.py +45 -0
- rucio/web/__init__.py +13 -0
- rucio/web/rest/__init__.py +13 -0
- rucio/web/rest/flaskapi/__init__.py +13 -0
- rucio/web/rest/flaskapi/authenticated_bp.py +27 -0
- rucio/web/rest/flaskapi/v1/__init__.py +13 -0
- rucio/web/rest/flaskapi/v1/accountlimits.py +236 -0
- rucio/web/rest/flaskapi/v1/accounts.py +1103 -0
- rucio/web/rest/flaskapi/v1/archives.py +102 -0
- rucio/web/rest/flaskapi/v1/auth.py +1644 -0
- rucio/web/rest/flaskapi/v1/common.py +426 -0
- rucio/web/rest/flaskapi/v1/config.py +304 -0
- rucio/web/rest/flaskapi/v1/credentials.py +213 -0
- rucio/web/rest/flaskapi/v1/dids.py +2340 -0
- rucio/web/rest/flaskapi/v1/dirac.py +116 -0
- rucio/web/rest/flaskapi/v1/export.py +75 -0
- rucio/web/rest/flaskapi/v1/heartbeats.py +127 -0
- rucio/web/rest/flaskapi/v1/identities.py +285 -0
- rucio/web/rest/flaskapi/v1/import.py +132 -0
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +312 -0
- rucio/web/rest/flaskapi/v1/locks.py +358 -0
- rucio/web/rest/flaskapi/v1/main.py +91 -0
- rucio/web/rest/flaskapi/v1/meta_conventions.py +241 -0
- rucio/web/rest/flaskapi/v1/metrics.py +36 -0
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
- rucio/web/rest/flaskapi/v1/ping.py +88 -0
- rucio/web/rest/flaskapi/v1/redirect.py +366 -0
- rucio/web/rest/flaskapi/v1/replicas.py +1894 -0
- rucio/web/rest/flaskapi/v1/requests.py +998 -0
- rucio/web/rest/flaskapi/v1/rses.py +2250 -0
- rucio/web/rest/flaskapi/v1/rules.py +854 -0
- rucio/web/rest/flaskapi/v1/scopes.py +159 -0
- rucio/web/rest/flaskapi/v1/subscriptions.py +650 -0
- rucio/web/rest/flaskapi/v1/templates/auth_crash.html +80 -0
- rucio/web/rest/flaskapi/v1/templates/auth_granted.html +82 -0
- rucio/web/rest/flaskapi/v1/traces.py +137 -0
- rucio/web/rest/flaskapi/v1/types.py +20 -0
- rucio/web/rest/flaskapi/v1/vos.py +278 -0
- rucio/web/rest/main.py +18 -0
- rucio/web/rest/metrics.py +27 -0
- rucio/web/rest/ping.py +27 -0
- rucio-37.0.0rc1.data/data/rucio/etc/alembic.ini.template +71 -0
- rucio-37.0.0rc1.data/data/rucio/etc/alembic_offline.ini.template +74 -0
- rucio-37.0.0rc1.data/data/rucio/etc/globus-config.yml.template +5 -0
- rucio-37.0.0rc1.data/data/rucio/etc/ldap.cfg.template +30 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.atlas.client.template +43 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.template +241 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio_multi_vo.cfg.template +217 -0
- rucio-37.0.0rc1.data/data/rucio/requirements.server.txt +297 -0
- rucio-37.0.0rc1.data/data/rucio/tools/bootstrap.py +34 -0
- rucio-37.0.0rc1.data/data/rucio/tools/merge_rucio_configs.py +144 -0
- rucio-37.0.0rc1.data/data/rucio/tools/reset_database.py +40 -0
- rucio-37.0.0rc1.data/scripts/rucio +133 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-account +74 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-collection-replica +46 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-rse +78 -0
- rucio-37.0.0rc1.data/scripts/rucio-admin +97 -0
- rucio-37.0.0rc1.data/scripts/rucio-atropos +60 -0
- rucio-37.0.0rc1.data/scripts/rucio-auditor +206 -0
- rucio-37.0.0rc1.data/scripts/rucio-automatix +50 -0
- rucio-37.0.0rc1.data/scripts/rucio-bb8 +57 -0
- rucio-37.0.0rc1.data/scripts/rucio-cache-client +141 -0
- rucio-37.0.0rc1.data/scripts/rucio-cache-consumer +42 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-finisher +58 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-poller +66 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-preparer +37 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-receiver +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-stager +76 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-submitter +139 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-throttler +104 -0
- rucio-37.0.0rc1.data/scripts/rucio-dark-reaper +53 -0
- rucio-37.0.0rc1.data/scripts/rucio-dumper +160 -0
- rucio-37.0.0rc1.data/scripts/rucio-follower +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-hermes +54 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-cleaner +89 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-evaluator +137 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-injector +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-repairer +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-kronos +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-minos +53 -0
- rucio-37.0.0rc1.data/scripts/rucio-minos-temporary-expiration +50 -0
- rucio-37.0.0rc1.data/scripts/rucio-necromancer +120 -0
- rucio-37.0.0rc1.data/scripts/rucio-oauth-manager +63 -0
- rucio-37.0.0rc1.data/scripts/rucio-reaper +83 -0
- rucio-37.0.0rc1.data/scripts/rucio-replica-recoverer +248 -0
- rucio-37.0.0rc1.data/scripts/rucio-rse-decommissioner +66 -0
- rucio-37.0.0rc1.data/scripts/rucio-storage-consistency-actions +74 -0
- rucio-37.0.0rc1.data/scripts/rucio-transmogrifier +77 -0
- rucio-37.0.0rc1.data/scripts/rucio-undertaker +76 -0
- rucio-37.0.0rc1.dist-info/METADATA +92 -0
- rucio-37.0.0rc1.dist-info/RECORD +487 -0
- rucio-37.0.0rc1.dist-info/WHEEL +5 -0
- rucio-37.0.0rc1.dist-info/licenses/AUTHORS.rst +100 -0
- rucio-37.0.0rc1.dist-info/licenses/LICENSE +201 -0
- rucio-37.0.0rc1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
Hermes is a daemon that get the messages and sends them to external services (influxDB, ES, ActiveMQ).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import calendar
|
|
20
|
+
import datetime
|
|
21
|
+
import functools
|
|
22
|
+
import json
|
|
23
|
+
import logging
|
|
24
|
+
import re
|
|
25
|
+
import smtplib
|
|
26
|
+
import sys
|
|
27
|
+
import threading
|
|
28
|
+
import time
|
|
29
|
+
from configparser import NoOptionError, NoSectionError
|
|
30
|
+
from email.mime.text import MIMEText
|
|
31
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
|
32
|
+
|
|
33
|
+
import requests
|
|
34
|
+
from requests.auth import HTTPBasicAuth
|
|
35
|
+
|
|
36
|
+
import rucio.db.sqla.util
|
|
37
|
+
from rucio.common.config import config_get, config_get_bool, config_get_list
|
|
38
|
+
from rucio.common.exception import DatabaseException
|
|
39
|
+
from rucio.common.logging import formatted_logger, setup_logging
|
|
40
|
+
from rucio.common.stomp_utils import ListenerBase, StompConnectionManager
|
|
41
|
+
from rucio.core.message import delete_messages, retrieve_messages
|
|
42
|
+
from rucio.core.monitor import MetricManager
|
|
43
|
+
from rucio.daemons.common import run_daemon
|
|
44
|
+
|
|
45
|
+
if TYPE_CHECKING:
|
|
46
|
+
from collections.abc import Iterable
|
|
47
|
+
from types import FrameType
|
|
48
|
+
|
|
49
|
+
from rucio.common.types import LoggerFunction
|
|
50
|
+
from rucio.daemons.common import HeartbeatHandler
|
|
51
|
+
|
|
52
|
+
logging.getLogger("requests").setLevel(logging.CRITICAL)
|
|
53
|
+
|
|
54
|
+
METRICS = MetricManager(module=__name__)
|
|
55
|
+
graceful_stop = threading.Event()
|
|
56
|
+
DAEMON_NAME = "hermes"
|
|
57
|
+
|
|
58
|
+
RECONNECT_COUNTER = METRICS.counter(
|
|
59
|
+
name="reconnect.{host}",
|
|
60
|
+
documentation="Counts Hermes reconnects to different ActiveMQ brokers",
|
|
61
|
+
labelnames=("host",),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def default(datetype: Union[datetime.date, datetime.datetime]) -> str:
|
|
66
|
+
if isinstance(datetype, (datetime.date, datetime.datetime)):
|
|
67
|
+
return datetype.isoformat()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class HermesListener(ListenerBase):
|
|
71
|
+
"""
|
|
72
|
+
Hermes Listener
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def deliver_emails(messages: "Iterable[dict[str, Any]]", logger: "LoggerFunction") -> list[int]:
|
|
77
|
+
"""
|
|
78
|
+
Sends emails
|
|
79
|
+
|
|
80
|
+
:param messages: The list of messages.
|
|
81
|
+
:param logger: The logger object.
|
|
82
|
+
|
|
83
|
+
:returns: List of message_id to delete
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
email_from = config_get("messaging-hermes", "email_from")
|
|
87
|
+
send_email = config_get_bool(
|
|
88
|
+
"messaging-hermes", "send_email", raise_exception=False, default=True
|
|
89
|
+
)
|
|
90
|
+
to_delete = []
|
|
91
|
+
for message in messages:
|
|
92
|
+
if message['event_type'] == 'email':
|
|
93
|
+
msg = MIMEText(message['payload']['body'])
|
|
94
|
+
msg['From'] = email_from
|
|
95
|
+
msg['To'] = ', '.join(message['payload']['to'])
|
|
96
|
+
msg['Subject'] = message['payload']['subject']
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
if send_email:
|
|
100
|
+
smtp = smtplib.SMTP()
|
|
101
|
+
smtp.connect()
|
|
102
|
+
smtp.sendmail(
|
|
103
|
+
msg["From"], message["payload"]["to"], msg.as_string()
|
|
104
|
+
)
|
|
105
|
+
smtp.quit()
|
|
106
|
+
to_delete.append(message["id"])
|
|
107
|
+
except Exception as error:
|
|
108
|
+
logger(logging.ERROR, "Cannot send email : %s", str(error))
|
|
109
|
+
else:
|
|
110
|
+
to_delete.append(message["id"])
|
|
111
|
+
continue
|
|
112
|
+
return to_delete
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def submit_to_elastic(
|
|
116
|
+
messages: "Iterable[dict[str, Any]]",
|
|
117
|
+
endpoint: str,
|
|
118
|
+
logger: "LoggerFunction"
|
|
119
|
+
) -> int:
|
|
120
|
+
"""
|
|
121
|
+
Aggregate a list of message to ElasticSearch
|
|
122
|
+
|
|
123
|
+
:param messages: The list of messages.
|
|
124
|
+
:param endpoint: The ES endpoint were to send the messages.
|
|
125
|
+
:param logger: The logger object.
|
|
126
|
+
|
|
127
|
+
:returns: HTTP status code. 200 and 204 OK. Rest is failure.
|
|
128
|
+
"""
|
|
129
|
+
text = ""
|
|
130
|
+
elastic_username = config_get("hermes", "elastic_username",
|
|
131
|
+
raise_exception=False, default=None)
|
|
132
|
+
elastic_password = config_get("hermes", "elastic_password",
|
|
133
|
+
raise_exception=False, default=None)
|
|
134
|
+
auth = None
|
|
135
|
+
if elastic_username and elastic_password:
|
|
136
|
+
auth = HTTPBasicAuth(elastic_username, elastic_password)
|
|
137
|
+
|
|
138
|
+
for message in messages:
|
|
139
|
+
text += '{ "index":{ } }\n%s\n' % json.dumps(message, default=default)
|
|
140
|
+
res = requests.post(endpoint,
|
|
141
|
+
data=text,
|
|
142
|
+
headers={"Content-Type": "application/json"},
|
|
143
|
+
auth=auth)
|
|
144
|
+
return res.status_code
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def aggregate_to_influx(
|
|
148
|
+
messages: "Iterable[dict[str, Any]]",
|
|
149
|
+
bin_size: str,
|
|
150
|
+
endpoint: str,
|
|
151
|
+
logger: "LoggerFunction"
|
|
152
|
+
) -> int:
|
|
153
|
+
"""
|
|
154
|
+
Aggregate a list of message using a certain bin_size
|
|
155
|
+
and submit them to a InfluxDB endpoint
|
|
156
|
+
|
|
157
|
+
:param messages: The list of messages.
|
|
158
|
+
:param bin_size: The size of the bins for the aggregation (e.g. 10m, 1h, etc.).
|
|
159
|
+
:param endpoint: The InfluxDB endpoint were to send the messages.
|
|
160
|
+
:param logger: The logger object.
|
|
161
|
+
|
|
162
|
+
:returns: HTTP status code. 200 and 204 OK. Rest is failure.
|
|
163
|
+
"""
|
|
164
|
+
bins = {}
|
|
165
|
+
dtime = datetime.datetime.now()
|
|
166
|
+
microsecond = dtime.microsecond
|
|
167
|
+
|
|
168
|
+
for message in messages:
|
|
169
|
+
event_type = message["event_type"]
|
|
170
|
+
payload = message["payload"]
|
|
171
|
+
if event_type in ["transfer-failed", "transfer-done"]:
|
|
172
|
+
if not payload["transferred_at"]:
|
|
173
|
+
logger(logging.WARNING,
|
|
174
|
+
"No transferred_at for message. Reason : %s",
|
|
175
|
+
payload["reason"])
|
|
176
|
+
continue
|
|
177
|
+
transferred_at = time.strptime(
|
|
178
|
+
payload["transferred_at"], "%Y-%m-%d %H:%M:%S"
|
|
179
|
+
)
|
|
180
|
+
if bin_size == "1m":
|
|
181
|
+
transferred_at = int(calendar.timegm(transferred_at)) * 1000000000
|
|
182
|
+
transferred_at += microsecond
|
|
183
|
+
if transferred_at not in bins:
|
|
184
|
+
bins[transferred_at] = {}
|
|
185
|
+
src_rse, dest_rse, activity = (
|
|
186
|
+
payload["src-rse"],
|
|
187
|
+
payload["dst-rse"],
|
|
188
|
+
payload["activity"],
|
|
189
|
+
)
|
|
190
|
+
activity = re.sub(" ", r"\ ", activity)
|
|
191
|
+
key = f"transfer,activity={activity!s},src_rse={src_rse!s},dst_rse={dest_rse!s}"
|
|
192
|
+
if key not in bins[transferred_at]:
|
|
193
|
+
bins[transferred_at][key] = [0, 0, 0, 0]
|
|
194
|
+
if event_type == "transfer-done":
|
|
195
|
+
bins[transferred_at][key][0] += 1
|
|
196
|
+
bins[transferred_at][key][1] += payload["bytes"]
|
|
197
|
+
if event_type == "transfer-failed":
|
|
198
|
+
bins[transferred_at][key][2] += 1
|
|
199
|
+
bins[transferred_at][key][3] += payload["bytes"]
|
|
200
|
+
elif event_type in ["deletion-failed", "deletion-done"]:
|
|
201
|
+
created_at = message["created_at"]
|
|
202
|
+
if bin_size == "1m":
|
|
203
|
+
created_at = created_at.replace(
|
|
204
|
+
second=0, microsecond=0, tzinfo=datetime.timezone.utc
|
|
205
|
+
).timestamp()
|
|
206
|
+
created_at = int(created_at) * 1000000000
|
|
207
|
+
created_at += microsecond
|
|
208
|
+
if created_at not in bins:
|
|
209
|
+
bins[created_at] = {}
|
|
210
|
+
rse = payload["rse"]
|
|
211
|
+
key = f"deletion,rse={rse!s}"
|
|
212
|
+
if key not in bins[created_at]:
|
|
213
|
+
bins[created_at][key] = [0, 0, 0, 0]
|
|
214
|
+
if event_type == "deletion-done":
|
|
215
|
+
bins[created_at][key][0] += 1
|
|
216
|
+
bins[created_at][key][1] += payload["bytes"]
|
|
217
|
+
if event_type == "deletion-failed":
|
|
218
|
+
bins[created_at][key][2] += 1
|
|
219
|
+
bins[created_at][key][3] += payload["bytes"]
|
|
220
|
+
|
|
221
|
+
points = ""
|
|
222
|
+
for timestamp, entries in bins.items():
|
|
223
|
+
for key, metrics in entries.items():
|
|
224
|
+
event_type = key.split(",")[0]
|
|
225
|
+
points += (f"{key!s} "
|
|
226
|
+
f"nb_{event_type!s}_done={metrics[0]!s},"
|
|
227
|
+
f"bytes_{event_type!s}_done={metrics[1]!s},"
|
|
228
|
+
f"nb_{event_type!s}_failed={metrics[2]!s},"
|
|
229
|
+
f"bytes_{event_type!s}_failed={metrics[3]!s} "
|
|
230
|
+
rf"{timestamp!s}\n")
|
|
231
|
+
|
|
232
|
+
influx_token = config_get("hermes", "influxdb_token", False, None)
|
|
233
|
+
headers = {}
|
|
234
|
+
if influx_token:
|
|
235
|
+
headers["Authorization"] = f"Token {influx_token!s}"
|
|
236
|
+
if points:
|
|
237
|
+
res = requests.post(endpoint, headers=headers, data=points)
|
|
238
|
+
logger(logging.DEBUG, "%s", str(res.text))
|
|
239
|
+
return res.status_code
|
|
240
|
+
return 204
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def build_message_dict(
|
|
244
|
+
bulk: int,
|
|
245
|
+
thread: int,
|
|
246
|
+
total_threads: int,
|
|
247
|
+
message_dict: dict[str, list[dict[str, Any]]],
|
|
248
|
+
logger: "LoggerFunction",
|
|
249
|
+
service: Optional[str] = None,
|
|
250
|
+
) -> None:
|
|
251
|
+
"""
|
|
252
|
+
Retrieves messages from the database and builds a dictionary with the keys being the services, and the values a list of the messages (built up of dictionary / json information)
|
|
253
|
+
|
|
254
|
+
:param bulk: Integer for number of messages to retrieve.
|
|
255
|
+
:param thread: Passed to thread in retrieve_messages for Identifier of the caller thread as an integer.
|
|
256
|
+
:param total_threads: Passed to total_threads for Maximum number of threads as an integer.
|
|
257
|
+
:param message_dict: Either empty dictionary to be built, or build upon when using query_by_service.
|
|
258
|
+
:param logger: The logger object.
|
|
259
|
+
:param service: When passed, only returns messages table for this specific service.
|
|
260
|
+
|
|
261
|
+
:returns: None, but builds on the dictionary message_dict passed to this fuction (for when querying multiple services).
|
|
262
|
+
"""
|
|
263
|
+
start_time = time.time()
|
|
264
|
+
messages = retrieve_messages(
|
|
265
|
+
bulk=bulk,
|
|
266
|
+
old_mode=False,
|
|
267
|
+
thread=thread,
|
|
268
|
+
total_threads=total_threads,
|
|
269
|
+
service_filter=service,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
if messages:
|
|
273
|
+
if service is not None:
|
|
274
|
+
# query_by_service dictionary build behaviour
|
|
275
|
+
message_dict[service] = messages.copy()
|
|
276
|
+
logger(
|
|
277
|
+
logging.DEBUG,
|
|
278
|
+
"Retrieved %i messages retrieved in %s seconds for %s service.",
|
|
279
|
+
len(messages),
|
|
280
|
+
time.time() - start_time,
|
|
281
|
+
service,
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
else:
|
|
285
|
+
# default dictionary build behaviour
|
|
286
|
+
for message in messages:
|
|
287
|
+
service = message["services"]
|
|
288
|
+
if service is not None:
|
|
289
|
+
if service not in message_dict:
|
|
290
|
+
message_dict[service] = []
|
|
291
|
+
message_dict[service].append(message)
|
|
292
|
+
logger(
|
|
293
|
+
logging.DEBUG,
|
|
294
|
+
"Retrieved %i messages retrieved in %s seconds",
|
|
295
|
+
len(messages),
|
|
296
|
+
time.time() - start_time,
|
|
297
|
+
)
|
|
298
|
+
else:
|
|
299
|
+
logger(
|
|
300
|
+
logging.INFO,
|
|
301
|
+
"No messages retrieved in %s seconds",
|
|
302
|
+
time.time() - start_time,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def hermes(once: bool = False, bulk: int = 1000, sleep_time: int = 10) -> None:
|
|
307
|
+
"""
|
|
308
|
+
Creates a Hermes Worker that can submit messages to different services (InfluXDB, ElasticSearch, ActiveMQ)
|
|
309
|
+
The list of services need to be define in the config service in the hermes section.
|
|
310
|
+
The list of endpoints need to be defined in rucio.cfg in the hermes section.
|
|
311
|
+
|
|
312
|
+
:param once: Run only once.
|
|
313
|
+
:param bulk: The number of requests to process.
|
|
314
|
+
:param sleep_time: Time between two cycles.
|
|
315
|
+
"""
|
|
316
|
+
run_daemon(
|
|
317
|
+
once=once,
|
|
318
|
+
graceful_stop=graceful_stop,
|
|
319
|
+
executable=DAEMON_NAME,
|
|
320
|
+
partition_wait_time=1,
|
|
321
|
+
sleep_time=sleep_time,
|
|
322
|
+
run_once_fnc=functools.partial(
|
|
323
|
+
run_once,
|
|
324
|
+
bulk=bulk,
|
|
325
|
+
),
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> bool:
|
|
330
|
+
|
|
331
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
332
|
+
try:
|
|
333
|
+
services_list = config_get_list("hermes", "services_list")
|
|
334
|
+
except (NoOptionError, NoSectionError, RuntimeError):
|
|
335
|
+
logger(logging.DEBUG, "No services found, exiting")
|
|
336
|
+
sys.exit(1)
|
|
337
|
+
|
|
338
|
+
if "influx" in services_list:
|
|
339
|
+
influx_endpoint = None
|
|
340
|
+
try:
|
|
341
|
+
influx_endpoint = config_get("hermes", "influxdb_endpoint", False, None)
|
|
342
|
+
if not influx_endpoint:
|
|
343
|
+
logger(
|
|
344
|
+
logging.ERROR,
|
|
345
|
+
"InfluxDB defined in the services list, but no endpoint can be found",
|
|
346
|
+
)
|
|
347
|
+
except Exception as err:
|
|
348
|
+
logger(logging.ERROR, str(err))
|
|
349
|
+
if "elastic" in services_list:
|
|
350
|
+
elastic_endpoint = None
|
|
351
|
+
try:
|
|
352
|
+
elastic_endpoint = config_get("hermes", "elastic_endpoint", False, None)
|
|
353
|
+
if not elastic_endpoint:
|
|
354
|
+
logger(
|
|
355
|
+
logging.ERROR,
|
|
356
|
+
"Elastic defined in the services list, but no endpoint can be found",
|
|
357
|
+
)
|
|
358
|
+
except Exception as err:
|
|
359
|
+
logger(logging.ERROR, str(err))
|
|
360
|
+
conns = None
|
|
361
|
+
if "activemq" in services_list:
|
|
362
|
+
conn_mgr = StompConnectionManager(config_section='messaging-hermes', logger=logger)
|
|
363
|
+
conn_mgr.set_listener_factory("rucio-hermes", HermesListener, heartbeats=conn_mgr.config.heartbeats)
|
|
364
|
+
|
|
365
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
366
|
+
message_dict = {}
|
|
367
|
+
query_by_service = config_get_bool("hermes", "query_by_service", default=False)
|
|
368
|
+
|
|
369
|
+
# query_by_service is a toggleable behaviour switch between collecting bulk number of messages across all services when false, to collecting bulk messages from each service when true.
|
|
370
|
+
if query_by_service:
|
|
371
|
+
for service in services_list:
|
|
372
|
+
build_message_dict(
|
|
373
|
+
bulk=bulk,
|
|
374
|
+
thread=worker_number,
|
|
375
|
+
total_threads=total_workers,
|
|
376
|
+
message_dict=message_dict,
|
|
377
|
+
logger=logger,
|
|
378
|
+
service=service,
|
|
379
|
+
)
|
|
380
|
+
else:
|
|
381
|
+
build_message_dict(
|
|
382
|
+
bulk=bulk,
|
|
383
|
+
thread=worker_number,
|
|
384
|
+
total_threads=total_workers,
|
|
385
|
+
message_dict=message_dict,
|
|
386
|
+
logger=logger
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
if message_dict:
|
|
390
|
+
to_delete = []
|
|
391
|
+
|
|
392
|
+
if "influx" in message_dict and influx_endpoint:
|
|
393
|
+
# For influxDB, bulk submission, either everything succeeds or fails
|
|
394
|
+
t_time = time.time()
|
|
395
|
+
logger(logging.DEBUG, "Will submit to influxDB")
|
|
396
|
+
try:
|
|
397
|
+
state = aggregate_to_influx(
|
|
398
|
+
messages=message_dict["influx"],
|
|
399
|
+
bin_size="1m",
|
|
400
|
+
endpoint=influx_endpoint,
|
|
401
|
+
logger=logger,
|
|
402
|
+
)
|
|
403
|
+
if state in [204, 200]:
|
|
404
|
+
logger(
|
|
405
|
+
logging.INFO,
|
|
406
|
+
"%s messages successfully submitted to influxDB in %s seconds",
|
|
407
|
+
len(message_dict["influx"]),
|
|
408
|
+
time.time() - t_time,
|
|
409
|
+
)
|
|
410
|
+
for message in message_dict["influx"]:
|
|
411
|
+
to_delete.append(message)
|
|
412
|
+
else:
|
|
413
|
+
logger(
|
|
414
|
+
logging.ERROR,
|
|
415
|
+
"Failure to submit %s messages to influxDB. Returned status: %s",
|
|
416
|
+
len(message_dict["influx"]),
|
|
417
|
+
state,
|
|
418
|
+
)
|
|
419
|
+
except Exception as error:
|
|
420
|
+
logger(logging.ERROR, "Error sending to InfluxDB : %s", str(error))
|
|
421
|
+
|
|
422
|
+
if "elastic" in message_dict and elastic_endpoint:
|
|
423
|
+
# For elastic, bulk submission, either everything succeeds or fails
|
|
424
|
+
t_time = time.time()
|
|
425
|
+
try:
|
|
426
|
+
state = submit_to_elastic(
|
|
427
|
+
messages=message_dict["elastic"],
|
|
428
|
+
endpoint=elastic_endpoint,
|
|
429
|
+
logger=logger,
|
|
430
|
+
)
|
|
431
|
+
if state in [200, 204]:
|
|
432
|
+
logger(
|
|
433
|
+
logging.INFO,
|
|
434
|
+
"%s messages successfully submitted to elastic in %s seconds",
|
|
435
|
+
len(message_dict["elastic"]),
|
|
436
|
+
time.time() - t_time,
|
|
437
|
+
)
|
|
438
|
+
for message in message_dict["elastic"]:
|
|
439
|
+
to_delete.append(message)
|
|
440
|
+
else:
|
|
441
|
+
logger(
|
|
442
|
+
logging.ERROR,
|
|
443
|
+
"Failure to submit %s messages to elastic. Returned status: %s",
|
|
444
|
+
len(message_dict["elastic"]),
|
|
445
|
+
state,
|
|
446
|
+
)
|
|
447
|
+
except Exception as error:
|
|
448
|
+
logger(logging.ERROR, "Error sending to Elastic : %s", str(error))
|
|
449
|
+
|
|
450
|
+
if "email" in message_dict:
|
|
451
|
+
t_time = time.time()
|
|
452
|
+
try:
|
|
453
|
+
messages_sent = deliver_emails(
|
|
454
|
+
messages=message_dict["email"], logger=logger
|
|
455
|
+
)
|
|
456
|
+
logger(
|
|
457
|
+
logging.INFO,
|
|
458
|
+
"%s messages successfully submitted by emails in %s seconds",
|
|
459
|
+
len(message_dict["email"]),
|
|
460
|
+
time.time() - t_time,
|
|
461
|
+
)
|
|
462
|
+
for message in message_dict["email"]:
|
|
463
|
+
if message["id"] in messages_sent:
|
|
464
|
+
to_delete.append(message)
|
|
465
|
+
except Exception as error:
|
|
466
|
+
logger(logging.ERROR, "Error sending email : %s", str(error))
|
|
467
|
+
|
|
468
|
+
if "activemq" in message_dict and conns:
|
|
469
|
+
t_time = time.time()
|
|
470
|
+
try:
|
|
471
|
+
messages_sent = conn_mgr.deliver_messages(messages=message_dict["activemq"])
|
|
472
|
+
logger(
|
|
473
|
+
logging.INFO,
|
|
474
|
+
"%s messages successfully submitted to ActiveMQ in %s seconds",
|
|
475
|
+
len(message_dict["activemq"]),
|
|
476
|
+
time.time() - t_time,
|
|
477
|
+
)
|
|
478
|
+
for message in message_dict["activemq"]:
|
|
479
|
+
if message["id"] in messages_sent:
|
|
480
|
+
to_delete.append(message)
|
|
481
|
+
except Exception as error:
|
|
482
|
+
logger(logging.ERROR, "Error sending to ActiveMQ : %s", str(error))
|
|
483
|
+
|
|
484
|
+
logger(logging.INFO, "Deleting %s messages", len(to_delete))
|
|
485
|
+
to_delete = [
|
|
486
|
+
{
|
|
487
|
+
"id": message["id"],
|
|
488
|
+
"created_at": message["created_at"],
|
|
489
|
+
"updated_at": message["created_at"],
|
|
490
|
+
"payload": str(message["payload"]),
|
|
491
|
+
"event_type": message["event_type"],
|
|
492
|
+
"services": message["services"]
|
|
493
|
+
}
|
|
494
|
+
for message in to_delete
|
|
495
|
+
]
|
|
496
|
+
delete_messages(messages=to_delete)
|
|
497
|
+
must_sleep = True
|
|
498
|
+
return must_sleep
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
502
|
+
"""
|
|
503
|
+
Graceful exit.
|
|
504
|
+
"""
|
|
505
|
+
logging.info("Caught CTRL-C - waiting for cycle to end before shutting down")
|
|
506
|
+
graceful_stop.set()
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
def run(
|
|
510
|
+
once: bool = False,
|
|
511
|
+
threads: int = 1,
|
|
512
|
+
bulk: int = 1000,
|
|
513
|
+
sleep_time: int = 10,
|
|
514
|
+
broker_timeout: int = 3,
|
|
515
|
+
) -> None:
|
|
516
|
+
"""
|
|
517
|
+
Starts up the hermes threads.
|
|
518
|
+
"""
|
|
519
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
520
|
+
logger = formatted_logger(logging.log, DAEMON_NAME + ' %s')
|
|
521
|
+
|
|
522
|
+
if rucio.db.sqla.util.is_old_db():
|
|
523
|
+
raise DatabaseException("Database was not updated, daemon won't start")
|
|
524
|
+
|
|
525
|
+
logger(logging.INFO, "starting hermes threads")
|
|
526
|
+
thread_list = []
|
|
527
|
+
for _ in range(threads):
|
|
528
|
+
her_thread = threading.Thread(target=hermes, kwargs={"once": once, "bulk": bulk, "sleep_time": sleep_time})
|
|
529
|
+
her_thread.start()
|
|
530
|
+
thread_list.append(her_thread)
|
|
531
|
+
|
|
532
|
+
logger(logging.DEBUG, thread_list)
|
|
533
|
+
while [thread.join(timeout=3.14) for thread in thread_list if thread.is_alive()]:
|
|
534
|
+
pass
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|