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,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.
|
|
@@ -0,0 +1,511 @@
|
|
|
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
|
+
This daemon consumes tracer messages from ActiveMQ and updates the atime for replicas.
|
|
17
|
+
"""
|
|
18
|
+
import functools
|
|
19
|
+
import logging
|
|
20
|
+
import re
|
|
21
|
+
from configparser import NoOptionError, NoSectionError
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
from json import dumps as jdumps
|
|
24
|
+
from json import loads as jloads
|
|
25
|
+
from queue import Queue
|
|
26
|
+
from threading import Event, Thread
|
|
27
|
+
from time import time
|
|
28
|
+
from typing import TYPE_CHECKING
|
|
29
|
+
|
|
30
|
+
import rucio.db.sqla.util
|
|
31
|
+
from rucio.common.config import config_get, config_get_int, config_get_list
|
|
32
|
+
from rucio.common.exception import DatabaseException, RSENotFound
|
|
33
|
+
from rucio.common.logging import formatted_logger, setup_logging
|
|
34
|
+
from rucio.common.stomp_utils import ListenerBase, StompConnectionManager
|
|
35
|
+
from rucio.common.stopwatch import Stopwatch
|
|
36
|
+
from rucio.common.types import InternalAccount, InternalScope, LoggerFunction
|
|
37
|
+
from rucio.core.did import list_parent_dids, touch_dids
|
|
38
|
+
from rucio.core.lock import touch_dataset_locks
|
|
39
|
+
from rucio.core.monitor import MetricManager
|
|
40
|
+
from rucio.core.replica import declare_bad_file_replicas, touch_collection_replicas, touch_replica
|
|
41
|
+
from rucio.core.rse import get_rse_id
|
|
42
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
43
|
+
from rucio.db.sqla.constants import BadFilesStatus, DIDType
|
|
44
|
+
|
|
45
|
+
if TYPE_CHECKING:
|
|
46
|
+
from collections.abc import Set
|
|
47
|
+
from types import FrameType
|
|
48
|
+
|
|
49
|
+
from stomp.utils import Frame
|
|
50
|
+
|
|
51
|
+
from rucio.common.stomp_utils import Connection
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
logging.getLogger("stomp").setLevel(logging.CRITICAL)
|
|
55
|
+
|
|
56
|
+
METRICS = MetricManager(module=__name__)
|
|
57
|
+
graceful_stop = Event()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class AMQConsumer(ListenerBase):
|
|
61
|
+
"""ActiveMQ message consumer"""
|
|
62
|
+
|
|
63
|
+
def __init__(self,
|
|
64
|
+
conn: "Connection",
|
|
65
|
+
queue: str,
|
|
66
|
+
chunksize: int,
|
|
67
|
+
subscription_id: str,
|
|
68
|
+
excluded_usrdns: "Set[str]",
|
|
69
|
+
dataset_queue: Queue,
|
|
70
|
+
bad_files_patterns: list[re.Pattern],
|
|
71
|
+
logger: LoggerFunction = logging.log,
|
|
72
|
+
**kwargs: dict) -> None:
|
|
73
|
+
super().__init__(conn=conn, logger=logger, **kwargs)
|
|
74
|
+
self.__queue = queue
|
|
75
|
+
self.__reports = []
|
|
76
|
+
self.__ids = []
|
|
77
|
+
self.__chunksize = chunksize
|
|
78
|
+
self.__subscription_id = subscription_id
|
|
79
|
+
# excluded states empty for the moment, maybe that should be recosidered in the future
|
|
80
|
+
self.__excluded_states = set([])
|
|
81
|
+
# exclude specific usrdns like GangaRBT
|
|
82
|
+
self.__excluded_usrdns = excluded_usrdns
|
|
83
|
+
self.__dataset_queue = dataset_queue
|
|
84
|
+
self.__bad_files_patterns = bad_files_patterns
|
|
85
|
+
|
|
86
|
+
@METRICS.count_it
|
|
87
|
+
def on_message(self, frame: "Frame") -> None:
|
|
88
|
+
appversion = 'dq2'
|
|
89
|
+
msg_id = frame.headers['message-id']
|
|
90
|
+
if 'appversion' in frame.headers:
|
|
91
|
+
appversion = frame.headers['appversion']
|
|
92
|
+
|
|
93
|
+
if 'resubmitted' in frame.headers:
|
|
94
|
+
METRICS.counter('received_resubmitted').inc()
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
if appversion == 'dq2':
|
|
98
|
+
self._conn.ack(msg_id, self.__subscription_id)
|
|
99
|
+
return
|
|
100
|
+
else:
|
|
101
|
+
report = jloads(frame.body) # type: ignore
|
|
102
|
+
except Exception:
|
|
103
|
+
# message is corrupt, not much to do here
|
|
104
|
+
# send count to graphite, send ack to broker and return
|
|
105
|
+
METRICS.counter('json_error').inc()
|
|
106
|
+
self._logger(logging.ERROR, 'json error', exc_info=True)
|
|
107
|
+
self._conn.ack(msg_id, self.__subscription_id)
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
self.__ids.append(msg_id)
|
|
111
|
+
self.__reports.append(report)
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
self._logger(logging.DEBUG,
|
|
115
|
+
"message received: %s %s %s",
|
|
116
|
+
str(report['eventType']),
|
|
117
|
+
report['filename'],
|
|
118
|
+
report['remoteSite'])
|
|
119
|
+
except Exception:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
if len(self.__ids) >= self.__chunksize:
|
|
123
|
+
self.__update_atime()
|
|
124
|
+
for msg_id in self.__ids:
|
|
125
|
+
self._conn.ack(msg_id, self.__subscription_id)
|
|
126
|
+
|
|
127
|
+
self.__reports = []
|
|
128
|
+
self.__ids = []
|
|
129
|
+
|
|
130
|
+
def __update_atime(self) -> None:
|
|
131
|
+
"""
|
|
132
|
+
Bulk update atime.
|
|
133
|
+
"""
|
|
134
|
+
replicas = []
|
|
135
|
+
rses = []
|
|
136
|
+
for report in self.__reports:
|
|
137
|
+
if 'vo' not in report:
|
|
138
|
+
report['vo'] = 'def'
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
# Identify suspicious files
|
|
142
|
+
try:
|
|
143
|
+
if self.__bad_files_patterns and report['eventType'] in ['get_sm', 'get_sm_a', 'get'] and 'clientState' in report and report['clientState'] not in ['DONE', 'FOUND_ROOT', 'ALREADY_DONE']:
|
|
144
|
+
for pattern in self.__bad_files_patterns:
|
|
145
|
+
if 'stateReason' in report and report['stateReason'] and isinstance(report['stateReason'], str) and pattern.match(report['stateReason']):
|
|
146
|
+
reason = report['stateReason'][:255]
|
|
147
|
+
if 'url' not in report or not report['url']:
|
|
148
|
+
self._logger(logging.ERROR, 'Missing url in the following trace : ' + str(report))
|
|
149
|
+
else:
|
|
150
|
+
try:
|
|
151
|
+
surl = report['url']
|
|
152
|
+
declare_bad_file_replicas([surl, ], reason=reason, issuer=InternalAccount('root', vo=report['vo']), status=BadFilesStatus.SUSPICIOUS)
|
|
153
|
+
self._logger(logging.INFO,
|
|
154
|
+
"Declare suspicious file %s with reason %s",
|
|
155
|
+
report['url'],
|
|
156
|
+
reason)
|
|
157
|
+
except Exception as error:
|
|
158
|
+
self._logger(logging.ERROR, 'Failed to declare suspicious file' + str(error))
|
|
159
|
+
except Exception as error:
|
|
160
|
+
self._logger(logging.ERROR, 'Problem with bad trace : %s . Error %s', str(report), str(error))
|
|
161
|
+
|
|
162
|
+
# check if scope in report. if not skip this one.
|
|
163
|
+
if 'scope' not in report:
|
|
164
|
+
METRICS.counter('missing_scope').inc()
|
|
165
|
+
if report['eventType'] != 'touch':
|
|
166
|
+
continue
|
|
167
|
+
else:
|
|
168
|
+
METRICS.counter('with_scope').inc()
|
|
169
|
+
report['scope'] = InternalScope(report['scope'], report['vo'])
|
|
170
|
+
|
|
171
|
+
# handle all events starting with get* and download and touch events.
|
|
172
|
+
if not report['eventType'].startswith('get') and not report['eventType'].startswith('sm_get') and not report['eventType'] == 'download' and not report['eventType'] == 'touch':
|
|
173
|
+
continue
|
|
174
|
+
if report['eventType'].endswith('_es'):
|
|
175
|
+
continue
|
|
176
|
+
METRICS.counter('total_get').inc()
|
|
177
|
+
if report['eventType'] == 'get':
|
|
178
|
+
METRICS.counter('dq2clients').inc()
|
|
179
|
+
elif report['eventType'] == 'get_sm' or report['eventType'] == 'sm_get':
|
|
180
|
+
if report['eventVersion'] == 'aCT':
|
|
181
|
+
METRICS.counter('panda_production_act').inc()
|
|
182
|
+
else:
|
|
183
|
+
METRICS.counter('panda_production').inc()
|
|
184
|
+
elif report['eventType'] == 'get_sm_a' or report['eventType'] == 'sm_get_a':
|
|
185
|
+
if report['eventVersion'] == 'aCT':
|
|
186
|
+
METRICS.counter('panda_analysis_act').inc()
|
|
187
|
+
else:
|
|
188
|
+
METRICS.counter('panda_analysis').inc()
|
|
189
|
+
elif report['eventType'] == 'download':
|
|
190
|
+
METRICS.counter('rucio_download').inc()
|
|
191
|
+
elif report['eventType'] == 'touch':
|
|
192
|
+
METRICS.counter('rucio_touch').inc()
|
|
193
|
+
else:
|
|
194
|
+
METRICS.counter('other_get').inc()
|
|
195
|
+
|
|
196
|
+
if report['eventType'] == 'download' or report['eventType'] == 'touch':
|
|
197
|
+
report['usrdn'] = report['account']
|
|
198
|
+
|
|
199
|
+
if report['usrdn'] in self.__excluded_usrdns:
|
|
200
|
+
continue
|
|
201
|
+
# handle touch and non-touch traces differently
|
|
202
|
+
if report['eventType'] != 'touch':
|
|
203
|
+
# check if the report has the right state.
|
|
204
|
+
if 'eventVersion' in report:
|
|
205
|
+
if report['eventVersion'] != 'aCT':
|
|
206
|
+
if report['clientState'] in self.__excluded_states:
|
|
207
|
+
continue
|
|
208
|
+
|
|
209
|
+
if 'remoteSite' not in report:
|
|
210
|
+
continue
|
|
211
|
+
if not report['remoteSite']:
|
|
212
|
+
continue
|
|
213
|
+
|
|
214
|
+
if 'filename' not in report:
|
|
215
|
+
if 'name' in report:
|
|
216
|
+
report['filename'] = report['name']
|
|
217
|
+
|
|
218
|
+
rses = report['remoteSite'].strip().split(',')
|
|
219
|
+
for rse in rses:
|
|
220
|
+
try:
|
|
221
|
+
rse_id = get_rse_id(rse=rse, vo=report['vo'])
|
|
222
|
+
except RSENotFound:
|
|
223
|
+
self._logger(logging.WARNING, "Cannot lookup rse_id for %s. Will skip this report.", rse)
|
|
224
|
+
METRICS.counter('rse_not_found').inc()
|
|
225
|
+
continue
|
|
226
|
+
replicas.append({'name': report['filename'], 'scope': report['scope'], 'rse': rse, 'rse_id': rse_id, 'accessed_at': datetime.utcfromtimestamp(report['traceTimeentryUnix']),
|
|
227
|
+
'traceTimeentryUnix': report['traceTimeentryUnix'], 'eventVersion': report['eventVersion']})
|
|
228
|
+
else:
|
|
229
|
+
# if touch event and if datasetScope is in the report then it means
|
|
230
|
+
# that there is no file scope/name and therefore only the dataset is
|
|
231
|
+
# put in the queue to be updated and the rest is skipped.
|
|
232
|
+
rse_id = None
|
|
233
|
+
rse = None
|
|
234
|
+
if 'remoteSite' in report:
|
|
235
|
+
rse = report['remoteSite']
|
|
236
|
+
try:
|
|
237
|
+
rse_id = get_rse_id(rse=rse, vo=report['vo'])
|
|
238
|
+
except RSENotFound:
|
|
239
|
+
self._logger(logging.WARNING, "Cannot lookup rse_id for %s.", rse)
|
|
240
|
+
METRICS.counter('rse_not_found').inc()
|
|
241
|
+
if 'datasetScope' in report:
|
|
242
|
+
self.__dataset_queue.put({'scope': InternalScope(report['datasetScope'], vo=report['vo']),
|
|
243
|
+
'name': report['dataset'],
|
|
244
|
+
'rse_id': rse_id,
|
|
245
|
+
'accessed_at': datetime.utcfromtimestamp(report['traceTimeentryUnix'])})
|
|
246
|
+
continue
|
|
247
|
+
else:
|
|
248
|
+
if 'remoteSite' not in report:
|
|
249
|
+
continue
|
|
250
|
+
replicas.append({'name': report['filename'],
|
|
251
|
+
'scope': report['scope'],
|
|
252
|
+
'rse': rse,
|
|
253
|
+
'rse_id': rse_id,
|
|
254
|
+
'accessed_at': datetime.utcfromtimestamp(report['traceTimeentryUnix'])})
|
|
255
|
+
|
|
256
|
+
except (KeyError, AttributeError):
|
|
257
|
+
self._logger(logging.ERROR, "Cannot handle report.", exc_info=True)
|
|
258
|
+
METRICS.counter('report_error').inc()
|
|
259
|
+
continue
|
|
260
|
+
except Exception:
|
|
261
|
+
self._logger(logging.ERROR, "Exception", exc_info=True)
|
|
262
|
+
continue
|
|
263
|
+
|
|
264
|
+
for did in list_parent_dids(report['scope'], report['filename']):
|
|
265
|
+
if did['type'] != DIDType.DATASET:
|
|
266
|
+
continue
|
|
267
|
+
# do not update _dis datasets
|
|
268
|
+
if did['scope'].external == 'panda' and '_dis' in did['name']:
|
|
269
|
+
continue
|
|
270
|
+
for rse in rses:
|
|
271
|
+
try:
|
|
272
|
+
rse_id = get_rse_id(rse=rse, vo=report['vo'])
|
|
273
|
+
except RSENotFound:
|
|
274
|
+
self._logger(logging.WARNING, "Cannot lookup rse_id for %s. Will skip this report.", rse)
|
|
275
|
+
METRICS.counter('rse_not_found').inc()
|
|
276
|
+
continue
|
|
277
|
+
self.__dataset_queue.put({'scope': did['scope'], 'name': did['name'], 'did_type': did['type'], 'rse_id': rse_id, 'accessed_at': datetime.utcfromtimestamp(report['traceTimeentryUnix'])})
|
|
278
|
+
|
|
279
|
+
if not replicas:
|
|
280
|
+
return
|
|
281
|
+
|
|
282
|
+
self._logger(logging.DEBUG, "trying to update replicas: %s", replicas)
|
|
283
|
+
|
|
284
|
+
stopwatch = Stopwatch()
|
|
285
|
+
try:
|
|
286
|
+
for replica in replicas:
|
|
287
|
+
# if touch replica hits a locked row put the trace back into queue for later retry
|
|
288
|
+
if not touch_replica(replica):
|
|
289
|
+
resubmit = {'filename': replica['name'],
|
|
290
|
+
'scope': replica['scope'].external,
|
|
291
|
+
'remoteSite': replica['rse'],
|
|
292
|
+
'traceTimeentryUnix': replica['traceTimeentryUnix'],
|
|
293
|
+
'eventType': 'get',
|
|
294
|
+
'usrdn': 'someuser',
|
|
295
|
+
'clientState': 'DONE',
|
|
296
|
+
'eventVersion': replica['eventVersion']}
|
|
297
|
+
if replica['scope'].vo != 'def':
|
|
298
|
+
resubmit['vo'] = replica['scope'].vo
|
|
299
|
+
self._conn.send(body=jdumps(resubmit), destination=self.__queue, headers={'appversion': 'rucio', 'resubmitted': '1'})
|
|
300
|
+
METRICS.counter('sent_resubmitted').inc()
|
|
301
|
+
METRICS.timer('update_atime').observe(stopwatch.elapsed)
|
|
302
|
+
except Exception:
|
|
303
|
+
self._logger(logging.ERROR, "Cannot update replicas.", exc_info=True)
|
|
304
|
+
METRICS.counter('update_error').inc()
|
|
305
|
+
|
|
306
|
+
METRICS.counter('updated_replicas').inc()
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def kronos_file(once: bool = False,
|
|
310
|
+
dataset_queue: "Queue | None" = None,
|
|
311
|
+
sleep_time: int = 60,
|
|
312
|
+
logger: LoggerFunction = logging.log) -> None:
|
|
313
|
+
"""
|
|
314
|
+
Main loop to consume tracer reports.
|
|
315
|
+
"""
|
|
316
|
+
bad_files_patterns = []
|
|
317
|
+
try:
|
|
318
|
+
patterns = config_get_list(section='kronos', option='bad_files_patterns', session=None)
|
|
319
|
+
for pat in patterns:
|
|
320
|
+
bad_files_patterns.append(re.compile(pat.strip()))
|
|
321
|
+
except (NoOptionError, NoSectionError, RuntimeError):
|
|
322
|
+
logger(logging.ERROR, "Failed to get bad_file_patterns")
|
|
323
|
+
bad_files_patterns.clear()
|
|
324
|
+
except Exception as error:
|
|
325
|
+
logger(logging.ERROR, f'Failed to get bad_file_patterns {str(error)}')
|
|
326
|
+
bad_files_patterns.clear()
|
|
327
|
+
|
|
328
|
+
excluded_usrdns = set(config_get('tracer-kronos', 'excluded_usrdns').split(','))
|
|
329
|
+
|
|
330
|
+
subscription_id = config_get('tracer-kronos', 'subscription_id')
|
|
331
|
+
stomp_conn_mngr = StompConnectionManager(config_section='tracer-kronos',
|
|
332
|
+
logger=logger)
|
|
333
|
+
stomp_conn_mngr.set_listener_factory('rucio-tracer-kronos',
|
|
334
|
+
AMQConsumer,
|
|
335
|
+
queue=config_get('tracer-kronos', 'queue'),
|
|
336
|
+
chunksize=config_get_int('tracer-kronos', 'chunksize'),
|
|
337
|
+
subscription_id=subscription_id,
|
|
338
|
+
excluded_usrdns=excluded_usrdns,
|
|
339
|
+
dataset_queue=dataset_queue,
|
|
340
|
+
bad_files_patterns=bad_files_patterns,
|
|
341
|
+
heartbeats=stomp_conn_mngr.config.heartbeats)
|
|
342
|
+
|
|
343
|
+
run_daemon(
|
|
344
|
+
once=once,
|
|
345
|
+
graceful_stop=graceful_stop,
|
|
346
|
+
executable='kronos-file',
|
|
347
|
+
partition_wait_time=1,
|
|
348
|
+
sleep_time=sleep_time,
|
|
349
|
+
run_once_fnc=functools.partial(
|
|
350
|
+
run_once_kronos_file,
|
|
351
|
+
stomp_conn_mngr=stomp_conn_mngr,
|
|
352
|
+
dataset_queue=dataset_queue, # type: ignore
|
|
353
|
+
sleep_time=sleep_time,
|
|
354
|
+
)
|
|
355
|
+
)
|
|
356
|
+
stomp_conn_mngr.disconnect()
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def run_once_kronos_file(heartbeat_handler: HeartbeatHandler,
|
|
360
|
+
stomp_conn_mngr: StompConnectionManager,
|
|
361
|
+
dataset_queue: Queue,
|
|
362
|
+
sleep_time: int,
|
|
363
|
+
**kwargs: dict) -> None:
|
|
364
|
+
"""
|
|
365
|
+
Run the amq consumer once.
|
|
366
|
+
"""
|
|
367
|
+
_, _, logger = heartbeat_handler.live()
|
|
368
|
+
|
|
369
|
+
stomp_conn_mngr.subscribe(id_=config_get('tracer-kronos', 'subscription_id'),
|
|
370
|
+
ack='client-individual',
|
|
371
|
+
destination=config_get('tracer-kronos', 'queue'),
|
|
372
|
+
headers={'activemq.prefetchSize': config_get_int('tracer-kronos', 'prefetch_size')})
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def kronos_dataset(dataset_queue: Queue, once: bool = False, sleep_time: int = 60) -> None:
|
|
376
|
+
return_values = {'heartbeat_handler': HeartbeatHandler("kronos-dataset", 10)}
|
|
377
|
+
run_daemon(
|
|
378
|
+
once=once,
|
|
379
|
+
graceful_stop=graceful_stop,
|
|
380
|
+
executable='kronos-dataset',
|
|
381
|
+
partition_wait_time=1,
|
|
382
|
+
sleep_time=sleep_time,
|
|
383
|
+
run_once_fnc=functools.partial(
|
|
384
|
+
run_once_kronos_dataset,
|
|
385
|
+
dataset_queue=dataset_queue,
|
|
386
|
+
return_values=return_values,
|
|
387
|
+
)
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
# once again for potential backlog
|
|
391
|
+
run_once_kronos_dataset(dataset_queue=dataset_queue,
|
|
392
|
+
return_values=return_values,
|
|
393
|
+
heartbeat_handler=return_values['heartbeat_handler'],
|
|
394
|
+
sleep_time=sleep_time)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def run_once_kronos_dataset(dataset_queue: Queue,
|
|
398
|
+
return_values: dict,
|
|
399
|
+
heartbeat_handler: "HeartbeatHandler | None",
|
|
400
|
+
**kwargs) -> None:
|
|
401
|
+
if heartbeat_handler is None:
|
|
402
|
+
if "heartbeat_handler" not in return_values.keys():
|
|
403
|
+
return_values["heartbeat_handler"] = HeartbeatHandler("kronos-dataset", 10)
|
|
404
|
+
heartbeat_handler = return_values["heartbeat_handler"]
|
|
405
|
+
|
|
406
|
+
_, _, logger = heartbeat_handler.live()
|
|
407
|
+
len_ds = dataset_queue.qsize()
|
|
408
|
+
datasets = {}
|
|
409
|
+
dslocks = {}
|
|
410
|
+
now = time()
|
|
411
|
+
for _ in range(0, len_ds):
|
|
412
|
+
dataset = dataset_queue.get()
|
|
413
|
+
did = '%s:%s' % (dataset['scope'].internal, dataset['name'])
|
|
414
|
+
rse = dataset['rse_id']
|
|
415
|
+
if did not in datasets:
|
|
416
|
+
datasets[did] = dataset['accessed_at']
|
|
417
|
+
else:
|
|
418
|
+
datasets[did] = max(datasets[did], dataset['accessed_at'])
|
|
419
|
+
|
|
420
|
+
if rse is None:
|
|
421
|
+
continue
|
|
422
|
+
if did not in dslocks:
|
|
423
|
+
dslocks[did] = {}
|
|
424
|
+
if rse not in dslocks[did]:
|
|
425
|
+
dslocks[did][rse] = dataset['accessed_at']
|
|
426
|
+
else:
|
|
427
|
+
dslocks[did][rse] = max(dataset['accessed_at'], dslocks[did][rse])
|
|
428
|
+
logger(logging.INFO, 'fetched %d datasets from queue (%ds)' % (len_ds, time() - now))
|
|
429
|
+
|
|
430
|
+
total, failed, start = 0, 0, time()
|
|
431
|
+
for did, accessed_at in datasets.items():
|
|
432
|
+
scope, name = did.split(':')
|
|
433
|
+
scope = InternalScope(scope, from_external=False)
|
|
434
|
+
update_did = {'scope': scope, 'name': name, 'type': DIDType.DATASET, 'accessed_at': accessed_at}
|
|
435
|
+
# if update fails, put back in queue and retry next time
|
|
436
|
+
if not touch_dids((update_did,)):
|
|
437
|
+
update_did['rse_id'] = None
|
|
438
|
+
dataset_queue.put(update_did)
|
|
439
|
+
failed += 1
|
|
440
|
+
total += 1
|
|
441
|
+
logger(logging.INFO, 'update done for %d datasets, %d failed (%ds)' % (total, failed, time() - start))
|
|
442
|
+
|
|
443
|
+
total, failed, start = 0, 0, time()
|
|
444
|
+
for did, rses in dslocks.items():
|
|
445
|
+
scope, name = did.split(':')
|
|
446
|
+
scope = InternalScope(scope, from_external=False)
|
|
447
|
+
for rse, accessed_at in rses.items():
|
|
448
|
+
update_dslock = {'scope': scope, 'name': name, 'rse_id': rse, 'accessed_at': accessed_at}
|
|
449
|
+
# if update fails, put back in queue and retry next time
|
|
450
|
+
if not touch_dataset_locks((update_dslock,)):
|
|
451
|
+
dataset_queue.put(update_dslock)
|
|
452
|
+
failed += 1
|
|
453
|
+
total += 1
|
|
454
|
+
logger(logging.INFO, 'update done for %d locks, %d failed (%ds)' % (total, failed, time() - start))
|
|
455
|
+
|
|
456
|
+
total, failed, start = 0, 0, time()
|
|
457
|
+
for did, rses in dslocks.items():
|
|
458
|
+
scope, name = did.split(':')
|
|
459
|
+
scope = InternalScope(scope, from_external=False)
|
|
460
|
+
for rse, accessed_at in rses.items():
|
|
461
|
+
update_dslock = {'scope': scope, 'name': name, 'rse_id': rse, 'accessed_at': accessed_at}
|
|
462
|
+
# if update fails, put back in queue and retry next time
|
|
463
|
+
if not touch_collection_replicas((update_dslock,)):
|
|
464
|
+
dataset_queue.put(update_dslock)
|
|
465
|
+
failed += 1
|
|
466
|
+
total += 1
|
|
467
|
+
logger(logging.INFO, 'update done for %d collection replicas, %d failed (%ds)' % (total, failed, time() - start))
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def stop(signum: "int | None" = None, frame: "FrameType | None" = None) -> None:
|
|
471
|
+
"""
|
|
472
|
+
Graceful exit.
|
|
473
|
+
"""
|
|
474
|
+
graceful_stop.set()
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def run(
|
|
478
|
+
once: bool = False,
|
|
479
|
+
threads: int = 1,
|
|
480
|
+
sleep_time_datasets: int = 60,
|
|
481
|
+
sleep_time_files: int = 60) -> None:
|
|
482
|
+
"""
|
|
483
|
+
Starts up the consumer threads
|
|
484
|
+
"""
|
|
485
|
+
setup_logging(process_name='tracer-kronos')
|
|
486
|
+
logger = formatted_logger(logging.log, 'Kronos %s')
|
|
487
|
+
|
|
488
|
+
if rucio.db.sqla.util.is_old_db():
|
|
489
|
+
raise DatabaseException('Database was not updated, daemon won\'t start')
|
|
490
|
+
|
|
491
|
+
dataset_queue = Queue()
|
|
492
|
+
logger(logging.INFO, 'starting tracer consumer threads')
|
|
493
|
+
|
|
494
|
+
thread_list = []
|
|
495
|
+
for _ in range(threads):
|
|
496
|
+
krf_thread = Thread(target=kronos_file, kwargs={'once': once,
|
|
497
|
+
'logger': logger,
|
|
498
|
+
'sleep_time': sleep_time_files,
|
|
499
|
+
'dataset_queue': dataset_queue})
|
|
500
|
+
krf_thread.start()
|
|
501
|
+
krd_thread = Thread(target=kronos_dataset, kwargs={'once': once,
|
|
502
|
+
'sleep_time': sleep_time_datasets,
|
|
503
|
+
'dataset_queue': dataset_queue})
|
|
504
|
+
krd_thread.start()
|
|
505
|
+
thread_list.append(krf_thread)
|
|
506
|
+
thread_list.append(krd_thread)
|
|
507
|
+
|
|
508
|
+
logger(logging.INFO, 'waiting for interrupts')
|
|
509
|
+
|
|
510
|
+
while [thread.join(timeout=3.) for thread in thread_list if thread.is_alive()]:
|
|
511
|
+
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.
|