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,117 @@
|
|
|
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
|
+
Abacus-RSE is a daemon to update RSE counters.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import logging
|
|
20
|
+
import threading
|
|
21
|
+
import time
|
|
22
|
+
from typing import TYPE_CHECKING
|
|
23
|
+
|
|
24
|
+
import rucio.db.sqla.util
|
|
25
|
+
from rucio.common import exception
|
|
26
|
+
from rucio.common.logging import setup_logging
|
|
27
|
+
from rucio.common.utils import get_thread_with_periodic_running_function
|
|
28
|
+
from rucio.core.rse_counter import fill_rse_counter_history_table, get_updated_rse_counters, update_rse_counter
|
|
29
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from types import FrameType
|
|
33
|
+
from typing import Optional
|
|
34
|
+
|
|
35
|
+
graceful_stop = threading.Event()
|
|
36
|
+
DAEMON_NAME = 'abacus-rse'
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def rse_update(
|
|
40
|
+
once: bool = False,
|
|
41
|
+
sleep_time: int = 10
|
|
42
|
+
) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Main loop to check and update the RSE Counters.
|
|
45
|
+
"""
|
|
46
|
+
run_daemon(
|
|
47
|
+
once=once,
|
|
48
|
+
graceful_stop=graceful_stop,
|
|
49
|
+
executable=DAEMON_NAME,
|
|
50
|
+
partition_wait_time=1,
|
|
51
|
+
sleep_time=sleep_time,
|
|
52
|
+
run_once_fnc=run_once,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def run_once(
|
|
57
|
+
heartbeat_handler: HeartbeatHandler,
|
|
58
|
+
**_kwargs
|
|
59
|
+
) -> None:
|
|
60
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
61
|
+
|
|
62
|
+
# Select a bunch of rses for to update for this worker
|
|
63
|
+
start = time.time() # NOQA
|
|
64
|
+
rse_ids = get_updated_rse_counters(total_workers=total_workers,
|
|
65
|
+
worker_number=worker_number)
|
|
66
|
+
logger(logging.DEBUG, 'Index query time %f size=%d' % (time.time() - start, len(rse_ids)))
|
|
67
|
+
|
|
68
|
+
# If the list is empty, sent the worker to sleep
|
|
69
|
+
if not rse_ids:
|
|
70
|
+
logger(logging.INFO, 'did not get any work')
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
for rse_id in rse_ids:
|
|
74
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
75
|
+
if graceful_stop.is_set():
|
|
76
|
+
break
|
|
77
|
+
start_time = time.time()
|
|
78
|
+
update_rse_counter(rse_id=rse_id)
|
|
79
|
+
logger(logging.DEBUG, 'update of rse "%s" took %f' % (rse_id, time.time() - start_time))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Graceful exit.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
graceful_stop.set()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def run(
|
|
91
|
+
once: bool = False,
|
|
92
|
+
threads: int = 1,
|
|
93
|
+
fill_history_table: bool = False,
|
|
94
|
+
sleep_time: int = 10
|
|
95
|
+
) -> None:
|
|
96
|
+
"""
|
|
97
|
+
Starts up the Abacus-RSE threads.
|
|
98
|
+
"""
|
|
99
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
100
|
+
|
|
101
|
+
if rucio.db.sqla.util.is_old_db():
|
|
102
|
+
raise exception.DatabaseException('Database was not updated, daemon won\'t start')
|
|
103
|
+
|
|
104
|
+
if once:
|
|
105
|
+
logging.info('main: executing one iteration only')
|
|
106
|
+
rse_update(once)
|
|
107
|
+
else:
|
|
108
|
+
logging.info('main: starting threads')
|
|
109
|
+
thread_list = [threading.Thread(target=rse_update, kwargs={'once': once, 'sleep_time': sleep_time}) for i in
|
|
110
|
+
range(0, threads)]
|
|
111
|
+
if fill_history_table:
|
|
112
|
+
thread_list.append(get_thread_with_periodic_running_function(3600, fill_rse_counter_history_table, graceful_stop))
|
|
113
|
+
[t.start() for t in thread_list]
|
|
114
|
+
logging.info('main: waiting for interrupts')
|
|
115
|
+
# Interruptible joins require a timeout.
|
|
116
|
+
while thread_list[0].is_alive():
|
|
117
|
+
[t.join(timeout=3.14) for t in thread_list]
|
|
@@ -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,242 @@
|
|
|
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
|
+
import datetime
|
|
16
|
+
import functools
|
|
17
|
+
import logging
|
|
18
|
+
import random
|
|
19
|
+
import threading
|
|
20
|
+
from sys import exc_info
|
|
21
|
+
from traceback import format_exception
|
|
22
|
+
from typing import TYPE_CHECKING
|
|
23
|
+
|
|
24
|
+
import rucio.core.lifetime_exception
|
|
25
|
+
import rucio.db.sqla.util
|
|
26
|
+
from rucio.common import exception
|
|
27
|
+
from rucio.common.exception import InvalidRSEExpression, RuleNotFound
|
|
28
|
+
from rucio.common.logging import setup_logging
|
|
29
|
+
from rucio.core.did import set_metadata
|
|
30
|
+
from rucio.core.lock import get_dataset_locks
|
|
31
|
+
from rucio.core.rse import get_rse_name, get_rse_vo
|
|
32
|
+
from rucio.core.rse_expression_parser import parse_expression
|
|
33
|
+
from rucio.core.rule import get_rules_beyond_eol, update_rule
|
|
34
|
+
from rucio.daemons.common import run_daemon
|
|
35
|
+
from rucio.db.sqla.constants import LifetimeExceptionsState
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from types import FrameType
|
|
39
|
+
from typing import Optional
|
|
40
|
+
|
|
41
|
+
from rucio.daemons.common import HeartbeatHandler
|
|
42
|
+
|
|
43
|
+
GRACEFUL_STOP = threading.Event()
|
|
44
|
+
DAEMON_NAME = 'atropos'
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def atropos(
|
|
48
|
+
date_check: datetime.datetime,
|
|
49
|
+
dry_run: bool,
|
|
50
|
+
grace_period: int,
|
|
51
|
+
purge_replicas: bool,
|
|
52
|
+
spread_period: bool,
|
|
53
|
+
unlock: bool,
|
|
54
|
+
once: bool,
|
|
55
|
+
sleep_time: int
|
|
56
|
+
) -> None:
|
|
57
|
+
"""
|
|
58
|
+
Creates an Atropos Worker that gets a list of rules which have an eol_at expired and delete them.
|
|
59
|
+
|
|
60
|
+
:param grace_period: The grace_period for the rules.
|
|
61
|
+
:param once: Run only once.
|
|
62
|
+
:param sleep_time: Thread sleep time after each chunk of work.
|
|
63
|
+
"""
|
|
64
|
+
run_daemon(
|
|
65
|
+
once=once,
|
|
66
|
+
graceful_stop=GRACEFUL_STOP,
|
|
67
|
+
executable=DAEMON_NAME,
|
|
68
|
+
partition_wait_time=10,
|
|
69
|
+
sleep_time=sleep_time,
|
|
70
|
+
run_once_fnc=functools.partial(
|
|
71
|
+
run_once,
|
|
72
|
+
date_check=date_check,
|
|
73
|
+
dry_run=dry_run,
|
|
74
|
+
grace_period=grace_period,
|
|
75
|
+
purge_replicas=purge_replicas,
|
|
76
|
+
spread_period=spread_period,
|
|
77
|
+
unlock=unlock
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def run_once(
|
|
83
|
+
heartbeat_handler: 'HeartbeatHandler',
|
|
84
|
+
activity: None, # NOQA: ARG001
|
|
85
|
+
date_check: datetime.datetime,
|
|
86
|
+
dry_run: bool,
|
|
87
|
+
grace_period: int,
|
|
88
|
+
purge_replicas: bool,
|
|
89
|
+
spread_period: int,
|
|
90
|
+
unlock: bool,
|
|
91
|
+
) -> None:
|
|
92
|
+
"""An iteration of an Atropos worker."""
|
|
93
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
94
|
+
logger(logging.DEBUG, 'Starting worker')
|
|
95
|
+
if not dry_run and date_check > datetime.datetime.utcnow():
|
|
96
|
+
logger(logging.ERROR, 'Atropos cannot run in non-dry-run mode for date in the future')
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
# Process the list of approved exceptions. In case a DID has
|
|
100
|
+
# multiple exceptions, the one with the expiration date further in
|
|
101
|
+
# the future is what matters.
|
|
102
|
+
summary = {}
|
|
103
|
+
lifetime_exceptions = {}
|
|
104
|
+
for excep in rucio.core.lifetime_exception.list_exceptions(exception_id=None, states=[LifetimeExceptionsState.APPROVED, ], session=None):
|
|
105
|
+
key = '{}:{}'.format(excep['scope'].internal, excep['name'])
|
|
106
|
+
if key not in lifetime_exceptions:
|
|
107
|
+
lifetime_exceptions[key] = excep['expires_at']
|
|
108
|
+
elif lifetime_exceptions[key] < excep['expires_at']:
|
|
109
|
+
lifetime_exceptions[key] = excep['expires_at']
|
|
110
|
+
logger(logging.DEBUG, '%d active exceptions', len(lifetime_exceptions))
|
|
111
|
+
|
|
112
|
+
rand = random.Random(worker_number) # noqa: S311
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
rules = get_rules_beyond_eol(date_check, worker_number, total_workers, session=None)
|
|
116
|
+
logger(logging.INFO, '%d rules to process', len(rules))
|
|
117
|
+
for rule_idx, rule in enumerate(rules, start=1):
|
|
118
|
+
did = '%s:%s' % (rule.scope, rule.name)
|
|
119
|
+
did_key = '{}:{}'.format(rule.scope.internal, rule.name)
|
|
120
|
+
logger(logging.DEBUG, 'Working on rule %s on DID %s on %s', rule.id, did, rule.rse_expression)
|
|
121
|
+
|
|
122
|
+
if (rule_idx % 1000) == 0:
|
|
123
|
+
logger(logging.INFO, '%s/%s rules processed', rule_idx, len(rules))
|
|
124
|
+
|
|
125
|
+
# We compute the expected eol_at
|
|
126
|
+
try:
|
|
127
|
+
rses = parse_expression(rule.rse_expression, filter_={'vo': rule.account.vo})
|
|
128
|
+
except InvalidRSEExpression:
|
|
129
|
+
logger(logging.WARNING, 'Rule %s has an RSE expression that results in an empty set: %s', rule.id, rule.rse_expression)
|
|
130
|
+
continue
|
|
131
|
+
eol_at = rucio.core.lifetime_exception.define_eol(rule.scope, rule.name, rses)
|
|
132
|
+
if eol_at != rule.eol_at:
|
|
133
|
+
logger(logging.WARNING, 'The computed eol %s differs from the one recorded %s for rule %s on %s at %s',
|
|
134
|
+
eol_at, rule.eol_at, rule.id, did, rule.rse_expression)
|
|
135
|
+
try:
|
|
136
|
+
update_rule(rule.id, options={'eol_at': eol_at})
|
|
137
|
+
except RuleNotFound:
|
|
138
|
+
logger(logging.WARNING, 'Cannot find rule %s on DID %s', rule.id, did)
|
|
139
|
+
continue
|
|
140
|
+
|
|
141
|
+
# Check the exceptions
|
|
142
|
+
if did_key in lifetime_exceptions:
|
|
143
|
+
if eol_at > lifetime_exceptions[did_key]:
|
|
144
|
+
logger(logging.INFO, 'Rule %s on DID %s on %s has longer expiration date than the one requested : %s',
|
|
145
|
+
rule.id, did, rule.rse_expression, lifetime_exceptions[did_key])
|
|
146
|
+
else:
|
|
147
|
+
# If eol_at < requested extension, update eol_at
|
|
148
|
+
logger(logging.INFO, 'Updating rule %s on DID %s on %s according to the exception till %s',
|
|
149
|
+
rule.id, did, rule.rse_expression, lifetime_exceptions[did_key])
|
|
150
|
+
eol_at = lifetime_exceptions[did_key]
|
|
151
|
+
try:
|
|
152
|
+
update_rule(rule.id, options={'eol_at': lifetime_exceptions[did_key]})
|
|
153
|
+
except RuleNotFound:
|
|
154
|
+
logger(logging.WARNING, 'Cannot find rule %s on DID %s', rule.id, did)
|
|
155
|
+
continue
|
|
156
|
+
|
|
157
|
+
# Now check that the new eol_at is expired
|
|
158
|
+
if eol_at and eol_at <= date_check:
|
|
159
|
+
set_metadata(scope=rule.scope, name=rule.name, key='eol_at', value=eol_at)
|
|
160
|
+
no_locks = True
|
|
161
|
+
for lock in get_dataset_locks(rule.scope, rule.name):
|
|
162
|
+
if lock['rule_id'] == rule[4]:
|
|
163
|
+
no_locks = False
|
|
164
|
+
if lock['rse_id'] not in summary:
|
|
165
|
+
summary[lock['rse_id']] = {}
|
|
166
|
+
if did_key not in summary[lock['rse_id']]:
|
|
167
|
+
summary[lock['rse_id']][did_key] = {'length': lock['length'] or 0, 'bytes': lock['bytes'] or 0}
|
|
168
|
+
if no_locks:
|
|
169
|
+
logger(logging.WARNING, 'Cannot find a lock for rule %s on DID %s', rule.id, did)
|
|
170
|
+
if not dry_run:
|
|
171
|
+
lifetime = grace_period + rand.randrange(spread_period + 1)
|
|
172
|
+
logger(logging.INFO, 'Setting %s seconds lifetime for rule %s', lifetime, rule.id)
|
|
173
|
+
options = {'lifetime': lifetime}
|
|
174
|
+
if purge_replicas:
|
|
175
|
+
options['purge_replicas'] = True
|
|
176
|
+
if rule.locked and unlock:
|
|
177
|
+
logger(logging.INFO, 'Unlocking rule %s', rule.id)
|
|
178
|
+
options['locked'] = False
|
|
179
|
+
try:
|
|
180
|
+
update_rule(rule.id, options=options)
|
|
181
|
+
except RuleNotFound:
|
|
182
|
+
logger(logging.WARNING, 'Cannot find rule %s on DID %s', rule.id, did)
|
|
183
|
+
continue
|
|
184
|
+
except Exception:
|
|
185
|
+
exc_type, exc_value, exc_traceback = exc_info()
|
|
186
|
+
logger(logging.CRITICAL, ''.join(format_exception(exc_type, exc_value, exc_traceback)).strip())
|
|
187
|
+
|
|
188
|
+
for rse_id in summary:
|
|
189
|
+
tot_size, tot_files, tot_datasets = 0, 0, 0
|
|
190
|
+
for did in summary[rse_id]:
|
|
191
|
+
tot_datasets += 1
|
|
192
|
+
tot_files += summary[rse_id][did].get('length', 0)
|
|
193
|
+
tot_size += summary[rse_id][did].get('bytes', 0)
|
|
194
|
+
vo = get_rse_vo(rse_id=rse_id)
|
|
195
|
+
logger(logging.INFO, 'For RSE %s%s %d datasets will be deleted representing %d files and %d bytes',
|
|
196
|
+
get_rse_name(rse_id=rse_id), '' if vo == 'def' else ' on VO ' + vo, tot_datasets, tot_files, tot_size)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def run(
|
|
200
|
+
date_check: datetime.datetime = datetime.datetime.utcnow(),
|
|
201
|
+
dry_run: bool = True,
|
|
202
|
+
grace_period: int = 86400,
|
|
203
|
+
purge_replicas: bool = False,
|
|
204
|
+
spread_period: int = 0,
|
|
205
|
+
unlock: bool = False,
|
|
206
|
+
once: bool = True,
|
|
207
|
+
sleep_time: int = 60,
|
|
208
|
+
threads: int = 1,
|
|
209
|
+
) -> None:
|
|
210
|
+
"""
|
|
211
|
+
Starts up the atropos threads.
|
|
212
|
+
"""
|
|
213
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
214
|
+
|
|
215
|
+
if rucio.db.sqla.util.is_old_db():
|
|
216
|
+
raise exception.DatabaseException('Database was not updated, daemon won\'t start')
|
|
217
|
+
|
|
218
|
+
if once:
|
|
219
|
+
logging.info('Will run only one iteration')
|
|
220
|
+
logging.info('starting atropos threads')
|
|
221
|
+
thread_list = [threading.Thread(target=atropos, kwargs={'date_check': date_check,
|
|
222
|
+
'dry_run': dry_run,
|
|
223
|
+
'grace_period': grace_period,
|
|
224
|
+
'purge_replicas': purge_replicas,
|
|
225
|
+
'spread_period': spread_period,
|
|
226
|
+
'unlock': unlock,
|
|
227
|
+
'once': once,
|
|
228
|
+
'sleep_time': sleep_time}) for i in range(0, threads)]
|
|
229
|
+
[t.start() for t in thread_list]
|
|
230
|
+
|
|
231
|
+
logging.info('waiting for interrupts')
|
|
232
|
+
|
|
233
|
+
# Interruptible joins require a timeout.
|
|
234
|
+
while thread_list:
|
|
235
|
+
thread_list = [t.join(timeout=3.14) for t in thread_list if t and t.is_alive()]
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
|
|
239
|
+
"""
|
|
240
|
+
Graceful exit.
|
|
241
|
+
"""
|
|
242
|
+
GRACEFUL_STOP.set()
|
|
@@ -0,0 +1,289 @@
|
|
|
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
|
+
import bz2
|
|
16
|
+
import glob
|
|
17
|
+
import logging
|
|
18
|
+
import os
|
|
19
|
+
import select
|
|
20
|
+
from datetime import datetime, timedelta
|
|
21
|
+
from queue import Empty as EmptyQueue
|
|
22
|
+
from typing import TYPE_CHECKING, Optional
|
|
23
|
+
|
|
24
|
+
from rucio.common import config
|
|
25
|
+
from rucio.common.dumper import LogPipeHandler, mkdir, temp_file
|
|
26
|
+
from rucio.common.dumper.consistency import Consistency
|
|
27
|
+
from rucio.common.types import InternalAccount, InternalScope
|
|
28
|
+
from rucio.common.utils import chunks
|
|
29
|
+
from rucio.core.quarantined_replica import add_quarantined_replicas
|
|
30
|
+
from rucio.core.replica import declare_bad_file_replicas, list_replicas
|
|
31
|
+
from rucio.core.rse import get_rse_id, get_rse_usage
|
|
32
|
+
from rucio.daemons.auditor import srmdumps
|
|
33
|
+
from rucio.daemons.auditor.hdfs import ReplicaFromHDFS
|
|
34
|
+
from rucio.db.sqla.constants import BadFilesStatus
|
|
35
|
+
|
|
36
|
+
if TYPE_CHECKING:
|
|
37
|
+
from collections.abc import Iterable
|
|
38
|
+
from configparser import RawConfigParser
|
|
39
|
+
from multiprocessing import Queue as QueueType
|
|
40
|
+
from multiprocessing.connection import Connection
|
|
41
|
+
from multiprocessing.synchronize import Event
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def consistency(
|
|
45
|
+
rse: str,
|
|
46
|
+
delta: timedelta,
|
|
47
|
+
configuration: "RawConfigParser",
|
|
48
|
+
cache_dir: str,
|
|
49
|
+
results_dir: str
|
|
50
|
+
) -> Optional[str]:
|
|
51
|
+
logger = logging.getLogger('auditor-worker')
|
|
52
|
+
rsedump, rsedate = srmdumps.download_rse_dump(rse, configuration, destdir=cache_dir)
|
|
53
|
+
results_path = os.path.join(results_dir, '{0}_{1}'.format(rse, rsedate.strftime('%Y%m%d'))) # pylint: disable=no-member
|
|
54
|
+
|
|
55
|
+
if os.path.exists(results_path + '.bz2') or os.path.exists(results_path):
|
|
56
|
+
logger.warning('Consistency check for "%s" (dump dated %s) already done, skipping check', rse, rsedate.strftime('%Y%m%d')) # pylint: disable=no-member
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
rrdump_prev = ReplicaFromHDFS.download(rse, rsedate - delta, cache_dir=cache_dir)
|
|
60
|
+
rrdump_next = ReplicaFromHDFS.download(rse, rsedate + delta, cache_dir=cache_dir)
|
|
61
|
+
results = Consistency.dump(
|
|
62
|
+
'consistency-manual',
|
|
63
|
+
rse,
|
|
64
|
+
rsedump,
|
|
65
|
+
rrdump_prev,
|
|
66
|
+
rrdump_next,
|
|
67
|
+
date=rsedate,
|
|
68
|
+
cache_dir=cache_dir,
|
|
69
|
+
)
|
|
70
|
+
mkdir(results_dir)
|
|
71
|
+
with temp_file(results_dir, results_path) as (output, _):
|
|
72
|
+
for result in results:
|
|
73
|
+
output.write('{0}\n'.format(result.csv()))
|
|
74
|
+
|
|
75
|
+
return results_path
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def guess_replica_info(
|
|
79
|
+
path: str
|
|
80
|
+
) -> tuple[Optional[str], str]:
|
|
81
|
+
"""Try to extract the scope and name from a path.
|
|
82
|
+
|
|
83
|
+
``path``: relative path to the file on the RSE.
|
|
84
|
+
|
|
85
|
+
Returns a ``tuple`` of which the first element is the scope of the
|
|
86
|
+
replica and the second element is its name.
|
|
87
|
+
"""
|
|
88
|
+
items = path.split('/')
|
|
89
|
+
if len(items) == 1:
|
|
90
|
+
return None, path
|
|
91
|
+
elif len(items) > 2 and items[0] in ['group', 'user']:
|
|
92
|
+
return '.'.join(items[0:2]), items[-1]
|
|
93
|
+
else:
|
|
94
|
+
return items[0], items[-1]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def bz2_compress_file(
|
|
98
|
+
source: str,
|
|
99
|
+
chunk_size: int = 65000
|
|
100
|
+
) -> str:
|
|
101
|
+
"""Compress a file with bzip2.
|
|
102
|
+
|
|
103
|
+
The destination is the path passed through ``source`` extended with
|
|
104
|
+
'.bz2'. The original file is deleted.
|
|
105
|
+
|
|
106
|
+
Errors are deliberately not handled gracefully. Any exceptions
|
|
107
|
+
should be propagated to the caller.
|
|
108
|
+
|
|
109
|
+
``source``: absolute path to the file to compress.
|
|
110
|
+
|
|
111
|
+
``chunk_size``: size (in bytes) of the chunks by which to read the file.
|
|
112
|
+
|
|
113
|
+
Returns the destination path.
|
|
114
|
+
"""
|
|
115
|
+
destination = '{}.bz2'.format(source)
|
|
116
|
+
with open(source) as plain, bz2.BZ2File(destination, 'w') as compressed:
|
|
117
|
+
while True:
|
|
118
|
+
chunk = plain.read(chunk_size)
|
|
119
|
+
if not chunk:
|
|
120
|
+
break
|
|
121
|
+
compressed.write(chunk.encode())
|
|
122
|
+
os.remove(source)
|
|
123
|
+
return destination
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def process_output(
|
|
127
|
+
output: str,
|
|
128
|
+
sanity_check: bool = True,
|
|
129
|
+
compress: bool = True
|
|
130
|
+
) -> None:
|
|
131
|
+
"""Perform post-consistency-check actions.
|
|
132
|
+
|
|
133
|
+
DARK files are put in the quarantined-replica table so that they
|
|
134
|
+
may be deleted by the Dark Reaper. LOST files are reported as
|
|
135
|
+
suspicious so that they may be further checked by the cloud squads.
|
|
136
|
+
|
|
137
|
+
``output``: absolute path to the file
|
|
138
|
+
produced by ``consistency()``. It must maintain its naming
|
|
139
|
+
convention.
|
|
140
|
+
|
|
141
|
+
If ``sanity_check`` is ``True`` (default) and the number of entries
|
|
142
|
+
in the output file is deemed excessive, the actions are aborted.
|
|
143
|
+
|
|
144
|
+
If ``compress`` is ``True`` (default), the file is compressed with
|
|
145
|
+
bzip2 after the actions are successfully performed.
|
|
146
|
+
"""
|
|
147
|
+
logger = logging.getLogger('auditor-worker')
|
|
148
|
+
dark_replicas = []
|
|
149
|
+
lost_replicas = []
|
|
150
|
+
try:
|
|
151
|
+
with open(output) as f:
|
|
152
|
+
for line in f:
|
|
153
|
+
label, path = line.rstrip().split(',', 1)
|
|
154
|
+
scope, name = guess_replica_info(path)
|
|
155
|
+
if label == 'DARK':
|
|
156
|
+
dark_replicas.append({'path': path,
|
|
157
|
+
'scope': InternalScope(scope),
|
|
158
|
+
'name': name})
|
|
159
|
+
elif label == 'LOST':
|
|
160
|
+
lost_replicas.append({'scope': InternalScope(scope),
|
|
161
|
+
'name': name})
|
|
162
|
+
else:
|
|
163
|
+
raise ValueError('unexpected label')
|
|
164
|
+
# Since the file is read immediately after its creation, any error
|
|
165
|
+
# exposes a bug in the Auditor.
|
|
166
|
+
except Exception as error:
|
|
167
|
+
logger.critical('Error processing "%s"', output, exc_info=True)
|
|
168
|
+
raise error
|
|
169
|
+
|
|
170
|
+
rse = os.path.basename(output[:output.rfind('_')])
|
|
171
|
+
rse_id = get_rse_id(rse=rse)
|
|
172
|
+
usage = get_rse_usage(rse_id=rse_id, source='rucio')[0]
|
|
173
|
+
threshold = config.config_get_float('auditor', 'threshold', False, 0.1)
|
|
174
|
+
|
|
175
|
+
# Perform a basic sanity check by comparing the number of entries
|
|
176
|
+
# with the total number of files on the RSE. If the percentage is
|
|
177
|
+
# significant, there is most likely an issue with the site dump.
|
|
178
|
+
found_error = False
|
|
179
|
+
if len(dark_replicas) > threshold * usage['files']:
|
|
180
|
+
logger.warning('Number of DARK files is exceeding threshold: "%s"',
|
|
181
|
+
output)
|
|
182
|
+
found_error = True
|
|
183
|
+
if len(lost_replicas) > threshold * usage['files']:
|
|
184
|
+
logger.warning('Number of LOST files is exceeding threshold: "%s"',
|
|
185
|
+
output)
|
|
186
|
+
found_error = True
|
|
187
|
+
if found_error and sanity_check:
|
|
188
|
+
raise AssertionError('sanity check failed')
|
|
189
|
+
|
|
190
|
+
# While converting LOST replicas to PFNs, entries that do not
|
|
191
|
+
# correspond to a replica registered in Rucio are silently dropped.
|
|
192
|
+
lost_pfns = [r['rses'][rse_id][0] for chunk in chunks(lost_replicas, 1000) for r in list_replicas(chunk) if rse_id in r['rses']]
|
|
193
|
+
|
|
194
|
+
for chunk in chunks(dark_replicas, 1000):
|
|
195
|
+
add_quarantined_replicas(rse_id=rse_id, replicas=chunk)
|
|
196
|
+
logger.debug('Processed %d DARK files from "%s"', len(dark_replicas),
|
|
197
|
+
output)
|
|
198
|
+
declare_bad_file_replicas(lost_pfns, reason='Reported by Auditor',
|
|
199
|
+
issuer=InternalAccount('root'), status=BadFilesStatus.SUSPICIOUS)
|
|
200
|
+
logger.debug('Processed %d LOST files from "%s"', len(lost_replicas),
|
|
201
|
+
output)
|
|
202
|
+
|
|
203
|
+
if compress:
|
|
204
|
+
destination = bz2_compress_file(output)
|
|
205
|
+
logger.debug('Compressed "%s"', destination)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def check(
|
|
209
|
+
queue: "QueueType",
|
|
210
|
+
retry: "QueueType",
|
|
211
|
+
terminate: "Event",
|
|
212
|
+
logpipe: "Connection",
|
|
213
|
+
cache_dir: str,
|
|
214
|
+
results_dir: str,
|
|
215
|
+
keep_dumps: bool,
|
|
216
|
+
delta_in_days: int
|
|
217
|
+
) -> None:
|
|
218
|
+
logger = logging.getLogger('auditor-worker')
|
|
219
|
+
lib_logger = logging.getLogger('dumper')
|
|
220
|
+
|
|
221
|
+
loglevel = logging.getLevelName(config.config_get('common', 'loglevel', False, 'DEBUG'))
|
|
222
|
+
logger.setLevel(loglevel)
|
|
223
|
+
lib_logger.setLevel(loglevel)
|
|
224
|
+
|
|
225
|
+
handler = LogPipeHandler(logpipe)
|
|
226
|
+
logger.addHandler(handler)
|
|
227
|
+
lib_logger.addHandler(handler)
|
|
228
|
+
|
|
229
|
+
formatter = logging.Formatter(
|
|
230
|
+
"%(asctime)s %(name)-22s %(levelname)-8s [PID %(process)8d] %(message)s"
|
|
231
|
+
)
|
|
232
|
+
handler.setFormatter(formatter)
|
|
233
|
+
|
|
234
|
+
delta = timedelta(days=delta_in_days)
|
|
235
|
+
|
|
236
|
+
configuration = srmdumps.parse_configuration()
|
|
237
|
+
|
|
238
|
+
while not terminate.is_set():
|
|
239
|
+
try:
|
|
240
|
+
rse, attempts = queue.get(timeout=30)
|
|
241
|
+
except EmptyQueue:
|
|
242
|
+
continue
|
|
243
|
+
start = datetime.now()
|
|
244
|
+
try:
|
|
245
|
+
logger.debug('Checking "%s"', rse)
|
|
246
|
+
output = consistency(rse, delta, configuration, cache_dir,
|
|
247
|
+
results_dir)
|
|
248
|
+
if output:
|
|
249
|
+
process_output(output)
|
|
250
|
+
except:
|
|
251
|
+
elapsed = (datetime.now() - start).total_seconds() / 60
|
|
252
|
+
logger.error('Check of "%s" failed in %d minutes, %d remaining attempts', rse, elapsed, attempts, exc_info=True)
|
|
253
|
+
success = False
|
|
254
|
+
else:
|
|
255
|
+
elapsed = (datetime.now() - start).total_seconds() / 60
|
|
256
|
+
logger.info('SUCCESS checking "%s" in %d minutes', rse, elapsed)
|
|
257
|
+
success = True
|
|
258
|
+
|
|
259
|
+
if not keep_dumps:
|
|
260
|
+
remove = glob.glob(os.path.join(cache_dir, 'replicafromhdfs_{0}_*'.format(rse)))
|
|
261
|
+
remove.extend(glob.glob(os.path.join(cache_dir, 'ddmendpoint_{0}_*'.format(rse))))
|
|
262
|
+
logger.debug('Removing: %s', remove)
|
|
263
|
+
for fil in remove:
|
|
264
|
+
os.remove(fil)
|
|
265
|
+
|
|
266
|
+
if not success and attempts > 0:
|
|
267
|
+
retry.put((rse, attempts - 1))
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def activity_logger(
|
|
271
|
+
logpipes: "Iterable[Connection]",
|
|
272
|
+
logfilename: str,
|
|
273
|
+
terminate: "Event"
|
|
274
|
+
) -> None:
|
|
275
|
+
handler = logging.handlers.RotatingFileHandler(
|
|
276
|
+
logfilename,
|
|
277
|
+
maxBytes=20971520,
|
|
278
|
+
backupCount=10,
|
|
279
|
+
)
|
|
280
|
+
handler.setFormatter(logging.Formatter(fmt=None))
|
|
281
|
+
logger = logging.getLogger('auditor-logger-raw')
|
|
282
|
+
logger.addHandler(handler)
|
|
283
|
+
logger.setLevel(logging.CRITICAL) # The level of this logger is irrelevant
|
|
284
|
+
|
|
285
|
+
while not terminate.is_set():
|
|
286
|
+
ready, _, _ = select.select(logpipes, tuple(), tuple(), 30)
|
|
287
|
+
if ready:
|
|
288
|
+
for logpipe in ready:
|
|
289
|
+
logger.critical(logpipe.recv())
|