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,198 @@
|
|
|
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
|
+
OAuth Manager is a daemon which is responsible for:
|
|
17
|
+
- deletion of expired access tokens (in case there is a valid refresh token,
|
|
18
|
+
expired access tokens will be kept until refresh_token expires as well.)
|
|
19
|
+
- deletion of expired OAuth session parameters
|
|
20
|
+
- refreshing access tokens via their refresh tokens.
|
|
21
|
+
|
|
22
|
+
These 3 actions run consequently one after another in a loop with a sleeptime of 'looprate' seconds.
|
|
23
|
+
The maximum number of DB rows (tokens, parameters, refresh tokens) on which the script will operate
|
|
24
|
+
can be specified by 'max_rows' parameter.
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
import functools
|
|
29
|
+
import logging
|
|
30
|
+
import threading
|
|
31
|
+
import traceback
|
|
32
|
+
from re import match
|
|
33
|
+
from typing import TYPE_CHECKING
|
|
34
|
+
|
|
35
|
+
from sqlalchemy.exc import DatabaseError
|
|
36
|
+
|
|
37
|
+
import rucio.db.sqla.util
|
|
38
|
+
from rucio.common.exception import DatabaseException
|
|
39
|
+
from rucio.common.logging import setup_logging
|
|
40
|
+
from rucio.common.stopwatch import Stopwatch
|
|
41
|
+
from rucio.core.authentication import delete_expired_tokens
|
|
42
|
+
from rucio.core.monitor import MetricManager
|
|
43
|
+
from rucio.core.oidc import delete_expired_oauthrequests, refresh_jwt_tokens
|
|
44
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
45
|
+
from rucio.db.sqla.constants import ORACLE_CONNECTION_LOST_CONTACT_REGEX
|
|
46
|
+
|
|
47
|
+
if TYPE_CHECKING:
|
|
48
|
+
from types import FrameType
|
|
49
|
+
from typing import Optional
|
|
50
|
+
|
|
51
|
+
METRICS = MetricManager(module=__name__)
|
|
52
|
+
graceful_stop = threading.Event()
|
|
53
|
+
DAEMON_NAME = 'oauth-manager'
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def oauth_manager(once: bool = False, max_rows: int = 100, sleep_time: int = 300) -> None:
|
|
57
|
+
"""
|
|
58
|
+
Main loop to delete all expired tokens, refresh tokens eligible
|
|
59
|
+
for refresh and delete all expired OAuth session parameters.
|
|
60
|
+
It was decided to have only 1 daemon for all 3 of these cleanup activities.
|
|
61
|
+
|
|
62
|
+
:param once: If True, the loop is run just once, otherwise the daemon continues looping until stopped.
|
|
63
|
+
:param max_rows: Max number of DB rows to deal with per operation.
|
|
64
|
+
:param sleep_time: The number of seconds the daemon will wait before running next loop of operations.
|
|
65
|
+
|
|
66
|
+
:returns: None
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
run_daemon(
|
|
70
|
+
once=once,
|
|
71
|
+
graceful_stop=graceful_stop,
|
|
72
|
+
executable=DAEMON_NAME,
|
|
73
|
+
partition_wait_time=1,
|
|
74
|
+
sleep_time=sleep_time,
|
|
75
|
+
run_once_fnc=functools.partial(
|
|
76
|
+
run_once,
|
|
77
|
+
max_rows=max_rows,
|
|
78
|
+
sleep_time=sleep_time
|
|
79
|
+
),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def run_once(heartbeat_handler: HeartbeatHandler, max_rows: int, sleep_time: int, **_kwargs) -> None:
|
|
84
|
+
|
|
85
|
+
# make an initial heartbeat
|
|
86
|
+
heartbeat_handler.live()
|
|
87
|
+
|
|
88
|
+
stopwatch = Stopwatch()
|
|
89
|
+
|
|
90
|
+
ndeleted = 0
|
|
91
|
+
ndeletedreq = 0
|
|
92
|
+
nrefreshed = 0
|
|
93
|
+
|
|
94
|
+
# make a heartbeat
|
|
95
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
96
|
+
try:
|
|
97
|
+
# ACCESS TOKEN REFRESH - better to run first (in case some of the refreshed tokens needed deletion after this step)
|
|
98
|
+
logger(logging.INFO, '----- START ----- ACCESS TOKEN REFRESH ----- ')
|
|
99
|
+
logger(logging.INFO, 'starting to query tokens for automatic refresh')
|
|
100
|
+
nrefreshed = refresh_jwt_tokens(total_workers, worker_number, refreshrate=int(sleep_time), limit=max_rows)
|
|
101
|
+
logger(logging.INFO, 'successfully refreshed %i tokens', nrefreshed)
|
|
102
|
+
logger(logging.INFO, '----- END ----- ACCESS TOKEN REFRESH ----- ')
|
|
103
|
+
METRICS.counter(name='oauth_manager.tokens.refreshed').inc(nrefreshed)
|
|
104
|
+
|
|
105
|
+
except (DatabaseException, DatabaseError) as err:
|
|
106
|
+
if match('.*QueuePool.*', str(err.args[0])):
|
|
107
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
108
|
+
METRICS.counter('exceptions.{exception}').labels(exception=err.__class__.__name__).inc()
|
|
109
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(err.args[0])):
|
|
110
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
111
|
+
METRICS.counter('exceptions.{exception}').labels(exception=err.__class__.__name__).inc()
|
|
112
|
+
else:
|
|
113
|
+
logger(logging.CRITICAL, traceback.format_exc())
|
|
114
|
+
METRICS.counter('exceptions.{exception}').labels(exception=err.__class__.__name__).inc()
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
# waiting 1 sec as DBs does not store millisecond and tokens
|
|
118
|
+
# eligible for deletion after refresh might not get deleted otherwise
|
|
119
|
+
graceful_stop.wait(1)
|
|
120
|
+
|
|
121
|
+
# make a heartbeat
|
|
122
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
123
|
+
|
|
124
|
+
# EXPIRED TOKEN DELETION
|
|
125
|
+
logger(logging.INFO, '----- START ----- DELETION OF EXPIRED TOKENS ----- ')
|
|
126
|
+
logger(logging.INFO, 'starting to delete expired tokens')
|
|
127
|
+
ndeleted += delete_expired_tokens(total_workers, worker_number, limit=max_rows)
|
|
128
|
+
logger(logging.INFO, 'deleted %i expired tokens', ndeleted)
|
|
129
|
+
logger(logging.INFO, '----- END ----- DELETION OF EXPIRED TOKENS ----- ')
|
|
130
|
+
METRICS.counter(name='oauth_manager.tokens.deleted').inc(ndeleted)
|
|
131
|
+
|
|
132
|
+
except (DatabaseException, DatabaseError) as err:
|
|
133
|
+
if match('.*QueuePool.*', str(err.args[0])):
|
|
134
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
135
|
+
METRICS.counter('exceptions.{exception}').labels(exception=err.__class__.__name__).inc()
|
|
136
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(err.args[0])):
|
|
137
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
138
|
+
METRICS.counter('exceptions.{exception}').labels(exception=err.__class__.__name__).inc()
|
|
139
|
+
else:
|
|
140
|
+
logger(logging.CRITICAL, traceback.format_exc())
|
|
141
|
+
METRICS.counter('exceptions.{exception}').labels(exception=err.__class__.__name__).inc()
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
# make a heartbeat
|
|
145
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
146
|
+
|
|
147
|
+
# DELETING EXPIRED OAUTH SESSION PARAMETERS
|
|
148
|
+
logger(logging.INFO, '----- START ----- DELETION OF EXPIRED OAUTH SESSION REQUESTS ----- ')
|
|
149
|
+
logger(logging.INFO, 'starting deletion of expired OAuth session requests')
|
|
150
|
+
ndeletedreq += delete_expired_oauthrequests(total_workers, worker_number, limit=max_rows)
|
|
151
|
+
logger(logging.INFO, 'expired parameters of %i authentication requests were deleted', ndeletedreq)
|
|
152
|
+
logger(logging.INFO, '----- END ----- DELETION OF EXPIRED OAUTH SESSION REQUESTS ----- ')
|
|
153
|
+
METRICS.counter(name='oauth_manager.oauthreq.deleted').inc(ndeletedreq)
|
|
154
|
+
|
|
155
|
+
except (DatabaseException, DatabaseError) as err:
|
|
156
|
+
if match('.*QueuePool.*', str(err.args[0])):
|
|
157
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
158
|
+
METRICS.counter('exceptions.{exception}').labels(exception=err.__class__.__name__).inc()
|
|
159
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(err.args[0])):
|
|
160
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
161
|
+
METRICS.counter('exceptions.{exception}').labels(exception=err.__class__.__name__).inc()
|
|
162
|
+
else:
|
|
163
|
+
logger(logging.CRITICAL, traceback.format_exc())
|
|
164
|
+
METRICS.counter('exceptions.{exception}').labels(exception=err.__class__.__name__).inc()
|
|
165
|
+
|
|
166
|
+
stopwatch.stop()
|
|
167
|
+
logger(logging.INFO, 'took %f seconds to delete %i tokens, %i session parameters and refreshed %i tokens', stopwatch.elapsed, ndeleted, ndeletedreq, nrefreshed)
|
|
168
|
+
METRICS.timer('duration').observe(stopwatch.elapsed)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def run(once: bool = False, threads: int = 1, max_rows: int = 100, sleep_time: int = 300) -> None:
|
|
172
|
+
"""
|
|
173
|
+
Starts up the OAuth Manager threads.
|
|
174
|
+
"""
|
|
175
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
176
|
+
|
|
177
|
+
if rucio.db.sqla.util.is_old_db():
|
|
178
|
+
raise DatabaseException('Database was not updated, daemon won\'t start')
|
|
179
|
+
|
|
180
|
+
if once:
|
|
181
|
+
oauth_manager(once, max_rows, sleep_time)
|
|
182
|
+
else:
|
|
183
|
+
logging.info('OAuth Manager starting %s threads', str(threads))
|
|
184
|
+
threads = [threading.Thread(target=oauth_manager,
|
|
185
|
+
kwargs={'once': once,
|
|
186
|
+
'max_rows': max_rows,
|
|
187
|
+
'sleep_time': sleep_time}) for i in range(0, threads)]
|
|
188
|
+
_ = [t.start() for t in threads]
|
|
189
|
+
# Interruptible joins require a timeout.
|
|
190
|
+
while threads[0].is_alive():
|
|
191
|
+
_ = [t.join(timeout=3.14) for t in threads]
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
|
|
195
|
+
"""
|
|
196
|
+
Graceful exit.
|
|
197
|
+
"""
|
|
198
|
+
graceful_stop.set()
|
|
@@ -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,282 @@
|
|
|
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
|
+
Dark Reaper is a daemon to manage quarantined file deletion.
|
|
17
|
+
'''
|
|
18
|
+
|
|
19
|
+
import functools
|
|
20
|
+
import logging
|
|
21
|
+
import random
|
|
22
|
+
import sys
|
|
23
|
+
import threading
|
|
24
|
+
import time
|
|
25
|
+
import traceback
|
|
26
|
+
from typing import TYPE_CHECKING
|
|
27
|
+
|
|
28
|
+
import rucio.core.rse as rse_core
|
|
29
|
+
import rucio.db.sqla.util
|
|
30
|
+
from rucio.common import exception
|
|
31
|
+
from rucio.common.config import config_get_bool
|
|
32
|
+
from rucio.common.exception import ResourceTemporaryUnavailable, RSEAccessDenied, RSENotFound, ServiceUnavailable, SourceNotFound, VONotFound
|
|
33
|
+
from rucio.common.logging import setup_logging
|
|
34
|
+
from rucio.core.message import add_message
|
|
35
|
+
from rucio.core.monitor import MetricManager
|
|
36
|
+
from rucio.core.quarantined_replica import delete_quarantined_replicas, list_quarantined_replicas, list_rses_with_quarantined_replicas
|
|
37
|
+
from rucio.core.rse_expression_parser import parse_expression
|
|
38
|
+
from rucio.core.vo import list_vos
|
|
39
|
+
from rucio.daemons.common import run_daemon
|
|
40
|
+
from rucio.rse import rsemanager as rsemgr
|
|
41
|
+
|
|
42
|
+
if TYPE_CHECKING:
|
|
43
|
+
from collections.abc import Sequence
|
|
44
|
+
from types import FrameType
|
|
45
|
+
from typing import Optional
|
|
46
|
+
|
|
47
|
+
from rucio.common.types import LFNDict
|
|
48
|
+
from rucio.daemons.common import HeartbeatHandler
|
|
49
|
+
|
|
50
|
+
logging.getLogger("requests").setLevel(logging.CRITICAL)
|
|
51
|
+
|
|
52
|
+
METRICS = MetricManager(module=__name__)
|
|
53
|
+
GRACEFUL_STOP = threading.Event()
|
|
54
|
+
DAEMON_NAME = 'dark-reaper'
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def reaper(
|
|
58
|
+
rses: "Sequence[str]",
|
|
59
|
+
chunk_size: int = 100,
|
|
60
|
+
once: bool = False,
|
|
61
|
+
scheme: "Optional[str]" = None,
|
|
62
|
+
sleep_time: int = 300,
|
|
63
|
+
):
|
|
64
|
+
executable = DAEMON_NAME
|
|
65
|
+
if rses:
|
|
66
|
+
executable += ' '.join(sys.argv[1:])
|
|
67
|
+
run_daemon(
|
|
68
|
+
once=once,
|
|
69
|
+
graceful_stop=GRACEFUL_STOP,
|
|
70
|
+
executable=executable,
|
|
71
|
+
partition_wait_time=10,
|
|
72
|
+
sleep_time=sleep_time,
|
|
73
|
+
run_once_fnc=functools.partial(
|
|
74
|
+
run_once,
|
|
75
|
+
rses=rses,
|
|
76
|
+
chunk_size=chunk_size,
|
|
77
|
+
scheme=scheme,
|
|
78
|
+
),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def run_once(
|
|
83
|
+
rses: "Sequence[str]",
|
|
84
|
+
heartbeat_handler: "HeartbeatHandler",
|
|
85
|
+
chunk_size: int = 100,
|
|
86
|
+
scheme: "Optional[str]" = None,
|
|
87
|
+
**_kwargs,
|
|
88
|
+
):
|
|
89
|
+
"""
|
|
90
|
+
Main loop to select and delete files.
|
|
91
|
+
|
|
92
|
+
:param rses: List of RSEs the reaper should work against.
|
|
93
|
+
:param chunk_size: the size of chunk for deletion.
|
|
94
|
+
:param scheme: Force the reaper to use a particular protocol, e.g., mock.
|
|
95
|
+
"""
|
|
96
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
97
|
+
logger(logging.INFO, 'Starting Dark Reaper on RSEs: %s', ', '.join(rses))
|
|
98
|
+
|
|
99
|
+
nothing_to_do = True
|
|
100
|
+
rses_to_process = list(set(rses) & set(list_rses_with_quarantined_replicas()))
|
|
101
|
+
random.shuffle(rses_to_process)
|
|
102
|
+
for rse_id in rses_to_process:
|
|
103
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
104
|
+
# The following query returns the list of real replicas (deleted_replicas) and list of dark replicas (dark_replicas)
|
|
105
|
+
# Real replicas can be directly removed from the quarantine table
|
|
106
|
+
deleted_replicas, dark_replicas = list_quarantined_replicas(rse_id=rse_id,
|
|
107
|
+
limit=chunk_size,
|
|
108
|
+
worker_number=worker_number,
|
|
109
|
+
total_workers=total_workers)
|
|
110
|
+
|
|
111
|
+
rse_info = rsemgr.get_rse_info(rse_id=rse_id)
|
|
112
|
+
rse = rse_info['rse']
|
|
113
|
+
prot = rsemgr.create_protocol(rse_info, 'delete', scheme=scheme)
|
|
114
|
+
|
|
115
|
+
try:
|
|
116
|
+
prot.connect()
|
|
117
|
+
for replica in dark_replicas:
|
|
118
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
119
|
+
nothing_to_do = False
|
|
120
|
+
scope = ''
|
|
121
|
+
if replica['scope']:
|
|
122
|
+
scope = replica['scope'].external
|
|
123
|
+
try:
|
|
124
|
+
lfn: "LFNDict" = {
|
|
125
|
+
'scope': scope,
|
|
126
|
+
'name': replica['name'],
|
|
127
|
+
'path': replica['path']
|
|
128
|
+
}
|
|
129
|
+
pfn = str(list(rsemgr.lfns2pfns(rse_settings=rse_info,
|
|
130
|
+
lfns=[lfn],
|
|
131
|
+
operation='delete',
|
|
132
|
+
scheme=scheme).values())[0])
|
|
133
|
+
logger(logging.INFO, 'Deletion ATTEMPT of %s:%s as %s on %s', scope, replica['name'], pfn, rse)
|
|
134
|
+
start = time.time()
|
|
135
|
+
prot.delete(pfn)
|
|
136
|
+
METRICS.counter('deleted_replicas').inc()
|
|
137
|
+
duration = time.time() - start
|
|
138
|
+
logger(logging.INFO, 'Deletion SUCCESS of %s:%s as %s on %s in %s seconds', scope, replica['name'], pfn, rse, duration)
|
|
139
|
+
payload = {'scope': scope,
|
|
140
|
+
'name': replica['name'],
|
|
141
|
+
'rse': rse,
|
|
142
|
+
'rse_id': rse_id,
|
|
143
|
+
'file-size': replica.get('bytes') or 0,
|
|
144
|
+
'bytes': replica.get('bytes') or 0,
|
|
145
|
+
'url': pfn,
|
|
146
|
+
'duration': duration,
|
|
147
|
+
'protocol': prot.attributes['scheme']}
|
|
148
|
+
if replica['scope'].vo != 'def':
|
|
149
|
+
payload['vo'] = replica['scope'].vo
|
|
150
|
+
add_message('deletion-done', payload)
|
|
151
|
+
deleted_replicas.append(replica)
|
|
152
|
+
except SourceNotFound:
|
|
153
|
+
err_msg = ('Deletion NOTFOUND of %s:%s as %s on %s'
|
|
154
|
+
% (scope, replica['name'], pfn, rse))
|
|
155
|
+
logger(logging.WARNING, err_msg)
|
|
156
|
+
deleted_replicas.append(replica)
|
|
157
|
+
except (ServiceUnavailable, RSEAccessDenied, ResourceTemporaryUnavailable) as error:
|
|
158
|
+
err_msg = ('Deletion NOACCESS of %s:%s as %s on %s: %s'
|
|
159
|
+
% (scope, replica['name'], pfn, rse, str(error)))
|
|
160
|
+
logger(logging.WARNING, err_msg)
|
|
161
|
+
payload = {'scope': scope,
|
|
162
|
+
'name': replica['name'],
|
|
163
|
+
'rse': rse,
|
|
164
|
+
'rse_id': rse_id,
|
|
165
|
+
'file-size': replica['bytes'] or 0,
|
|
166
|
+
'bytes': replica['bytes'] or 0,
|
|
167
|
+
'url': pfn,
|
|
168
|
+
'reason': str(error),
|
|
169
|
+
'protocol': prot.attributes['scheme']}
|
|
170
|
+
if replica['scope'].vo != 'def':
|
|
171
|
+
payload['vo'] = replica['scope'].vo
|
|
172
|
+
add_message('deletion-failed', payload)
|
|
173
|
+
|
|
174
|
+
except Exception:
|
|
175
|
+
logging.critical(traceback.format_exc())
|
|
176
|
+
finally:
|
|
177
|
+
prot.close()
|
|
178
|
+
|
|
179
|
+
delete_quarantined_replicas(rse_id=rse_id, replicas=deleted_replicas)
|
|
180
|
+
|
|
181
|
+
must_sleep = False
|
|
182
|
+
if nothing_to_do:
|
|
183
|
+
logger(logging.INFO, 'Nothing to do')
|
|
184
|
+
must_sleep = True
|
|
185
|
+
return must_sleep
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
|
|
189
|
+
"""
|
|
190
|
+
Graceful exit.
|
|
191
|
+
"""
|
|
192
|
+
GRACEFUL_STOP.set()
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def run(
|
|
196
|
+
total_workers: int = 1,
|
|
197
|
+
chunk_size: int = 100,
|
|
198
|
+
once: bool = False,
|
|
199
|
+
rses: "Optional[list[str]]" = None,
|
|
200
|
+
scheme: "Optional[str]" = None,
|
|
201
|
+
exclude_rses: "Optional[str]" = None,
|
|
202
|
+
include_rses: "Optional[str]" = None,
|
|
203
|
+
vos: "Optional[list[str]]" = None,
|
|
204
|
+
delay_seconds: int = 0,
|
|
205
|
+
sleep_time: int = 300
|
|
206
|
+
) -> None:
|
|
207
|
+
"""
|
|
208
|
+
Starts up the reaper threads.
|
|
209
|
+
|
|
210
|
+
:param total_workers: The total number of workers.
|
|
211
|
+
:param chunk_size: the size of chunk for deletion.
|
|
212
|
+
:param once: If True, only runs one iteration of the main loop.
|
|
213
|
+
:param rses: List of RSEs the reaper should work against. If empty, it considers all RSEs (Single-VO only).
|
|
214
|
+
:param scheme: Force the reaper to use a particular protocol/scheme, e.g., mock.
|
|
215
|
+
:param exclude_rses: RSE expression to exclude RSEs from the Reaper.
|
|
216
|
+
:param include_rses: RSE expression to include RSEs.
|
|
217
|
+
:param vos: VOs on which to look for RSEs. Only used in multi-VO mode.
|
|
218
|
+
If None, we either use all VOs if run from "def", or the current VO otherwise.
|
|
219
|
+
"""
|
|
220
|
+
rses = rses or []
|
|
221
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
222
|
+
|
|
223
|
+
if rucio.db.sqla.util.is_old_db():
|
|
224
|
+
raise exception.DatabaseException('Database was not updated, daemon won\'t start')
|
|
225
|
+
|
|
226
|
+
logging.info('main: starting processes')
|
|
227
|
+
|
|
228
|
+
multi_vo = config_get_bool('common', 'multi_vo', raise_exception=False, default=False)
|
|
229
|
+
if not multi_vo:
|
|
230
|
+
if vos:
|
|
231
|
+
logging.warning('Ignoring argument vos, this is only applicable in a multi-VO setup.')
|
|
232
|
+
vos = ['def']
|
|
233
|
+
else:
|
|
234
|
+
if vos:
|
|
235
|
+
invalid = set(vos) - set([v['vo'] for v in list_vos()])
|
|
236
|
+
if invalid:
|
|
237
|
+
msg = 'VO{} {} cannot be found'.format('s' if len(invalid) > 1 else '',
|
|
238
|
+
', '.join([repr(v) for v in invalid]))
|
|
239
|
+
raise VONotFound(msg)
|
|
240
|
+
else:
|
|
241
|
+
vos = [v['vo'] for v in list_vos()]
|
|
242
|
+
logging.info('Dark Reaper: This instance will work on VO%s: %s'
|
|
243
|
+
% ('s' if len(vos) > 1 else '', ', '.join([v for v in vos])))
|
|
244
|
+
|
|
245
|
+
all_rses = []
|
|
246
|
+
for vo in vos:
|
|
247
|
+
all_rses.extend([rse['id'] for rse in rse_core.list_rses(filters={'vo': vo})])
|
|
248
|
+
|
|
249
|
+
if rses:
|
|
250
|
+
invalid = set(rses) - set([rse['rse'] for rse in all_rses])
|
|
251
|
+
if invalid:
|
|
252
|
+
msg = 'RSE{} {} cannot be found'.format('s' if len(invalid) > 1 else '',
|
|
253
|
+
', '.join([repr(rse) for rse in invalid]))
|
|
254
|
+
raise RSENotFound(msg)
|
|
255
|
+
rses = [rse for rse in all_rses if rse['rse'] in rses]
|
|
256
|
+
else:
|
|
257
|
+
rses = all_rses
|
|
258
|
+
|
|
259
|
+
if exclude_rses:
|
|
260
|
+
excluded_rses = [rse['id'] for rse in parse_expression(exclude_rses)]
|
|
261
|
+
rses = [rse for rse in rses if rse not in excluded_rses]
|
|
262
|
+
|
|
263
|
+
if include_rses:
|
|
264
|
+
included_rses = [rse['id'] for rse in parse_expression(include_rses)]
|
|
265
|
+
rses = [rse for rse in rses if rse in included_rses]
|
|
266
|
+
|
|
267
|
+
if not rses:
|
|
268
|
+
logging.error('Dark Reaper: No RSEs found. Exiting.')
|
|
269
|
+
return
|
|
270
|
+
|
|
271
|
+
threads = []
|
|
272
|
+
for worker in range(total_workers):
|
|
273
|
+
kwargs = {'rses': rses,
|
|
274
|
+
'once': once,
|
|
275
|
+
'chunk_size': chunk_size,
|
|
276
|
+
'scheme': scheme,
|
|
277
|
+
'sleep_time': sleep_time}
|
|
278
|
+
threads.append(threading.Thread(target=reaper, kwargs=kwargs,
|
|
279
|
+
name='Worker: %s, Total_Workers: %s' % (worker, total_workers)))
|
|
280
|
+
[t.start() for t in threads]
|
|
281
|
+
while threads[0].is_alive():
|
|
282
|
+
[t.join(timeout=3.14) for t in threads]
|