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,159 @@
|
|
|
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
|
+
Judge-Cleaner is a daemon to clean expired replication rules.
|
|
17
|
+
"""
|
|
18
|
+
import functools
|
|
19
|
+
import logging
|
|
20
|
+
import threading
|
|
21
|
+
import time
|
|
22
|
+
from copy import deepcopy
|
|
23
|
+
from datetime import datetime, timedelta
|
|
24
|
+
from random import randint
|
|
25
|
+
from re import match
|
|
26
|
+
from typing import TYPE_CHECKING, Optional
|
|
27
|
+
|
|
28
|
+
from sqlalchemy.exc import DatabaseError
|
|
29
|
+
|
|
30
|
+
import rucio.db.sqla.util
|
|
31
|
+
from rucio.common import exception
|
|
32
|
+
from rucio.common.exception import DatabaseException, RuleNotFound, UnsupportedOperation
|
|
33
|
+
from rucio.common.logging import setup_logging
|
|
34
|
+
from rucio.core.monitor import MetricManager
|
|
35
|
+
from rucio.core.rule import delete_rule, get_expired_rules
|
|
36
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
37
|
+
from rucio.db.sqla.constants import ORACLE_CONNECTION_LOST_CONTACT_REGEX, ORACLE_RESOURCE_BUSY_REGEX
|
|
38
|
+
from rucio.db.sqla.util import get_db_time
|
|
39
|
+
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from types import FrameType
|
|
42
|
+
|
|
43
|
+
METRICS = MetricManager(module=__name__)
|
|
44
|
+
graceful_stop = threading.Event()
|
|
45
|
+
DAEMON_NAME = 'judge-cleaner'
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def rule_cleaner(
|
|
49
|
+
once: bool = False,
|
|
50
|
+
sleep_time: int = 60
|
|
51
|
+
) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Main loop to check for expired replication rules
|
|
54
|
+
"""
|
|
55
|
+
paused_rules = {} # {rule_id: datetime}
|
|
56
|
+
run_daemon(
|
|
57
|
+
once=once,
|
|
58
|
+
graceful_stop=graceful_stop,
|
|
59
|
+
executable=DAEMON_NAME,
|
|
60
|
+
partition_wait_time=1,
|
|
61
|
+
sleep_time=sleep_time,
|
|
62
|
+
run_once_fnc=functools.partial(
|
|
63
|
+
run_once,
|
|
64
|
+
paused_rules=paused_rules,
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def run_once(
|
|
70
|
+
paused_rules: dict[str, datetime],
|
|
71
|
+
heartbeat_handler: HeartbeatHandler,
|
|
72
|
+
**_kwargs
|
|
73
|
+
) -> None:
|
|
74
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
75
|
+
|
|
76
|
+
start = time.time()
|
|
77
|
+
|
|
78
|
+
# Refresh paused rules
|
|
79
|
+
iter_paused_rules = deepcopy(paused_rules)
|
|
80
|
+
for key in iter_paused_rules:
|
|
81
|
+
if datetime.utcnow() > paused_rules[key]:
|
|
82
|
+
del paused_rules[key]
|
|
83
|
+
|
|
84
|
+
rules = get_expired_rules(total_workers=total_workers,
|
|
85
|
+
worker_number=worker_number,
|
|
86
|
+
limit=200,
|
|
87
|
+
blocked_rules=[key for key in paused_rules])
|
|
88
|
+
logger(logging.DEBUG, 'index query time %f fetch size is %d' % (time.time() - start, len(rules)))
|
|
89
|
+
|
|
90
|
+
if not rules:
|
|
91
|
+
logger(logging.DEBUG, 'did not get any work (paused_rules=%s)' % str(len(paused_rules)))
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
for rule in rules:
|
|
95
|
+
_, _, logger = heartbeat_handler.live()
|
|
96
|
+
rule_id = rule[0]
|
|
97
|
+
rule_expression = rule[1]
|
|
98
|
+
logger(logging.INFO, 'Deleting rule %s with expression %s' % (rule_id, rule_expression))
|
|
99
|
+
if graceful_stop.is_set():
|
|
100
|
+
break
|
|
101
|
+
try:
|
|
102
|
+
start = time.time()
|
|
103
|
+
delete_rule(rule_id=rule_id, nowait=True)
|
|
104
|
+
logger(logging.DEBUG, 'deletion of %s took %f' % (rule_id, time.time() - start))
|
|
105
|
+
except (DatabaseException, DatabaseError, UnsupportedOperation) as e:
|
|
106
|
+
if match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])):
|
|
107
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(600, 2400)) # noqa: S311
|
|
108
|
+
METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
|
|
109
|
+
logger(logging.WARNING, 'Locks detected for %s' % rule_id)
|
|
110
|
+
elif match('.*QueuePool.*', str(e.args[0])):
|
|
111
|
+
logger(logging.WARNING, 'DatabaseException', exc_info=True)
|
|
112
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
113
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(e.args[0])):
|
|
114
|
+
logger(logging.WARNING, 'DatabaseException', exc_info=True)
|
|
115
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
116
|
+
else:
|
|
117
|
+
logger(logging.ERROR, 'DatabaseException', exc_info=True)
|
|
118
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
119
|
+
except RuleNotFound:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
124
|
+
"""
|
|
125
|
+
Graceful exit.
|
|
126
|
+
"""
|
|
127
|
+
graceful_stop.set()
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def run(
|
|
131
|
+
once: bool = False,
|
|
132
|
+
threads: int = 1,
|
|
133
|
+
sleep_time: int = 60
|
|
134
|
+
) -> None:
|
|
135
|
+
"""
|
|
136
|
+
Starts up the Judge-Clean threads.
|
|
137
|
+
"""
|
|
138
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
139
|
+
|
|
140
|
+
if rucio.db.sqla.util.is_old_db():
|
|
141
|
+
raise exception.DatabaseException('Database was not updated, daemon won\'t start')
|
|
142
|
+
|
|
143
|
+
client_time, db_time = datetime.utcnow(), get_db_time()
|
|
144
|
+
max_offset = timedelta(hours=1, seconds=10)
|
|
145
|
+
if type(db_time) is datetime:
|
|
146
|
+
if db_time - client_time > max_offset or client_time - db_time > max_offset:
|
|
147
|
+
logging.critical('Offset between client and db time too big. Stopping Cleaner')
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
if once:
|
|
151
|
+
rule_cleaner(once)
|
|
152
|
+
else:
|
|
153
|
+
logging.info('Cleaner starting %s threads' % str(threads))
|
|
154
|
+
thread_list = [threading.Thread(target=rule_cleaner, kwargs={'once': once,
|
|
155
|
+
'sleep_time': sleep_time}) for i in range(0, threads)]
|
|
156
|
+
[t.start() for t in thread_list]
|
|
157
|
+
# Interruptible joins require a timeout.
|
|
158
|
+
while thread_list[0].is_alive():
|
|
159
|
+
[t.join(timeout=3.14) for t in thread_list]
|
|
@@ -0,0 +1,185 @@
|
|
|
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
|
+
Judge-Evaluator is a daemon to re-evaluate and execute replication rules.
|
|
17
|
+
"""
|
|
18
|
+
import copy
|
|
19
|
+
import functools
|
|
20
|
+
import logging
|
|
21
|
+
import threading
|
|
22
|
+
import time
|
|
23
|
+
import traceback
|
|
24
|
+
from datetime import datetime, timedelta
|
|
25
|
+
from random import randint
|
|
26
|
+
from re import match
|
|
27
|
+
from typing import TYPE_CHECKING, Optional
|
|
28
|
+
|
|
29
|
+
from sqlalchemy.exc import DatabaseError
|
|
30
|
+
from sqlalchemy.orm.exc import FlushError
|
|
31
|
+
|
|
32
|
+
import rucio.db.sqla.util
|
|
33
|
+
from rucio.common.exception import DatabaseException, DataIdentifierNotFound, ReplicationRuleCreationTemporaryFailed
|
|
34
|
+
from rucio.common.logging import setup_logging
|
|
35
|
+
from rucio.common.types import InternalScope
|
|
36
|
+
from rucio.core.monitor import MetricManager
|
|
37
|
+
from rucio.core.rule import delete_updated_did, get_updated_dids, re_evaluate_did
|
|
38
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
39
|
+
from rucio.db.sqla.constants import ORACLE_CONNECTION_LOST_CONTACT_REGEX, ORACLE_RESOURCE_BUSY_REGEX, ORACLE_UNIQUE_CONSTRAINT_VIOLATED_REGEX
|
|
40
|
+
|
|
41
|
+
if TYPE_CHECKING:
|
|
42
|
+
from types import FrameType
|
|
43
|
+
|
|
44
|
+
METRICS = MetricManager(module=__name__)
|
|
45
|
+
graceful_stop = threading.Event()
|
|
46
|
+
DAEMON_NAME = 'judge-evaluator'
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def re_evaluator(
|
|
50
|
+
once: bool = False,
|
|
51
|
+
sleep_time: int = 30,
|
|
52
|
+
did_limit: int = 100
|
|
53
|
+
) -> None:
|
|
54
|
+
"""
|
|
55
|
+
Main loop to check the re-evaluation of dids.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
paused_dids = {} # {(scope, name): datetime}
|
|
59
|
+
run_daemon(
|
|
60
|
+
once=once,
|
|
61
|
+
graceful_stop=graceful_stop,
|
|
62
|
+
executable=DAEMON_NAME,
|
|
63
|
+
partition_wait_time=1,
|
|
64
|
+
sleep_time=sleep_time,
|
|
65
|
+
run_once_fnc=functools.partial(
|
|
66
|
+
run_once,
|
|
67
|
+
did_limit=did_limit,
|
|
68
|
+
paused_dids=paused_dids,
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def run_once(
|
|
74
|
+
paused_dids: dict[tuple[str, str], datetime],
|
|
75
|
+
did_limit: int,
|
|
76
|
+
heartbeat_handler: HeartbeatHandler,
|
|
77
|
+
**_kwargs
|
|
78
|
+
) -> None:
|
|
79
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
80
|
+
|
|
81
|
+
# heartbeat
|
|
82
|
+
start = time.time() # NOQA
|
|
83
|
+
|
|
84
|
+
# Refresh paused dids
|
|
85
|
+
iter_paused_dids = copy.copy(paused_dids)
|
|
86
|
+
for key in iter_paused_dids:
|
|
87
|
+
if datetime.utcnow() > paused_dids[key]:
|
|
88
|
+
del paused_dids[key]
|
|
89
|
+
|
|
90
|
+
# Select a bunch of dids for re evaluation for this worker
|
|
91
|
+
dids = get_updated_dids(total_workers=total_workers,
|
|
92
|
+
worker_number=worker_number,
|
|
93
|
+
limit=did_limit,
|
|
94
|
+
blocked_dids=[(InternalScope(key[0], from_external=False), key[1]) for key in paused_dids])
|
|
95
|
+
logger(logging.DEBUG, 'index query time %f fetch size is %d (%d blocked)', time.time() - start, len(dids),
|
|
96
|
+
len([(InternalScope(key[0], from_external=False), key[1]) for key in paused_dids]))
|
|
97
|
+
|
|
98
|
+
# If the list is empty, sent the worker to sleep
|
|
99
|
+
if not dids:
|
|
100
|
+
logger(logging.DEBUG, 'did not get any work (paused_dids=%s)', str(len(paused_dids)))
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
done_dids = {}
|
|
104
|
+
for did in dids:
|
|
105
|
+
_, _, logger = heartbeat_handler.live()
|
|
106
|
+
if graceful_stop.is_set():
|
|
107
|
+
break
|
|
108
|
+
|
|
109
|
+
# Check if this did has already been operated on
|
|
110
|
+
did_tag = '%s:%s' % (did.scope.internal, did.name)
|
|
111
|
+
if did_tag in done_dids:
|
|
112
|
+
if did.rule_evaluation_action in done_dids[did_tag]:
|
|
113
|
+
logger(logging.DEBUG, 'evaluation of %s:%s already done', did.scope, did.name)
|
|
114
|
+
delete_updated_did(id_=did.id)
|
|
115
|
+
continue
|
|
116
|
+
else:
|
|
117
|
+
done_dids[did_tag] = []
|
|
118
|
+
|
|
119
|
+
# Jump paused dids
|
|
120
|
+
if (did.scope.internal, did.name) in paused_dids:
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
start_time = time.time()
|
|
125
|
+
re_evaluate_did(scope=did.scope, name=did.name, rule_evaluation_action=did.rule_evaluation_action)
|
|
126
|
+
logger(logging.DEBUG, 'evaluation of %s:%s took %f', did.scope, did.name, time.time() - start_time)
|
|
127
|
+
delete_updated_did(id_=did.id)
|
|
128
|
+
done_dids[did_tag].append(did.rule_evaluation_action)
|
|
129
|
+
except DataIdentifierNotFound:
|
|
130
|
+
delete_updated_did(id_=did.id)
|
|
131
|
+
except (DatabaseException, DatabaseError) as e:
|
|
132
|
+
if match(ORACLE_UNIQUE_CONSTRAINT_VIOLATED_REGEX, str(e.args[0])) or match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])):
|
|
133
|
+
paused_dids[(did.scope.internal, did.name)] = datetime.utcnow() + timedelta(seconds=randint(60, 600)) # noqa: S311
|
|
134
|
+
logger(logging.WARNING, 'Locks detected for %s:%s', did.scope, did.name)
|
|
135
|
+
METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
|
|
136
|
+
elif match('.*QueuePool.*', str(e.args[0])):
|
|
137
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
138
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
139
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(e.args[0])):
|
|
140
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
141
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
142
|
+
else:
|
|
143
|
+
logger(logging.ERROR, traceback.format_exc())
|
|
144
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
145
|
+
except ReplicationRuleCreationTemporaryFailed as e:
|
|
146
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
147
|
+
logger(logging.WARNING, 'Replica Creation temporary failed, retrying later for %s:%s', did.scope, did.name)
|
|
148
|
+
except FlushError as e:
|
|
149
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
150
|
+
logger(logging.WARNING, 'Flush error for %s:%s', did.scope, did.name)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
154
|
+
"""
|
|
155
|
+
Graceful exit.
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
graceful_stop.set()
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def run(
|
|
162
|
+
once: bool = False,
|
|
163
|
+
threads: int = 1,
|
|
164
|
+
sleep_time: int = 30,
|
|
165
|
+
did_limit: int = 100
|
|
166
|
+
) -> None:
|
|
167
|
+
"""
|
|
168
|
+
Starts up the Judge-Eval threads.
|
|
169
|
+
"""
|
|
170
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
171
|
+
|
|
172
|
+
if rucio.db.sqla.util.is_old_db():
|
|
173
|
+
raise DatabaseException('Database was not updated, daemon won\'t start')
|
|
174
|
+
|
|
175
|
+
if once:
|
|
176
|
+
re_evaluator(once=once, did_limit=did_limit)
|
|
177
|
+
else:
|
|
178
|
+
logging.info('Evaluator starting %s threads' % str(threads))
|
|
179
|
+
thread_list = [threading.Thread(target=re_evaluator, kwargs={'once': once,
|
|
180
|
+
'sleep_time': sleep_time,
|
|
181
|
+
'did_limit': did_limit}) for i in range(0, threads)]
|
|
182
|
+
[t.start() for t in thread_list]
|
|
183
|
+
# Interruptible joins require a timeout.
|
|
184
|
+
while thread_list[0].is_alive():
|
|
185
|
+
[t.join(timeout=3.14) for t in thread_list]
|
|
@@ -0,0 +1,162 @@
|
|
|
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
|
+
Judge-Injector is a daemon to asynchronously create replication rules
|
|
17
|
+
"""
|
|
18
|
+
import functools
|
|
19
|
+
import logging
|
|
20
|
+
import threading
|
|
21
|
+
import time
|
|
22
|
+
from copy import deepcopy
|
|
23
|
+
from datetime import datetime, timedelta
|
|
24
|
+
from random import randint
|
|
25
|
+
from re import match
|
|
26
|
+
from typing import TYPE_CHECKING, Optional
|
|
27
|
+
|
|
28
|
+
from sqlalchemy.exc import DatabaseError
|
|
29
|
+
|
|
30
|
+
import rucio.db.sqla.util
|
|
31
|
+
from rucio.common.exception import DatabaseException, InsufficientAccountLimit, ReplicationRuleCreationTemporaryFailed, RSEWriteBlocked, RuleNotFound
|
|
32
|
+
from rucio.common.logging import setup_logging
|
|
33
|
+
from rucio.core.monitor import MetricManager
|
|
34
|
+
from rucio.core.rule import get_injected_rules, inject_rule, update_rule
|
|
35
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
36
|
+
from rucio.db.sqla.constants import ORACLE_CONNECTION_LOST_CONTACT_REGEX, ORACLE_RESOURCE_BUSY_REGEX
|
|
37
|
+
|
|
38
|
+
if TYPE_CHECKING:
|
|
39
|
+
from types import FrameType
|
|
40
|
+
|
|
41
|
+
METRICS = MetricManager(module=__name__)
|
|
42
|
+
graceful_stop = threading.Event()
|
|
43
|
+
DAEMON_NAME = 'judge-injector'
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def rule_injector(
|
|
47
|
+
once: bool = False,
|
|
48
|
+
sleep_time: int = 60
|
|
49
|
+
) -> None:
|
|
50
|
+
"""
|
|
51
|
+
Main loop to check for asynchronous creation of replication rules
|
|
52
|
+
"""
|
|
53
|
+
paused_rules = {} # {rule_id: datetime}
|
|
54
|
+
run_daemon(
|
|
55
|
+
once=once,
|
|
56
|
+
graceful_stop=graceful_stop,
|
|
57
|
+
executable=DAEMON_NAME,
|
|
58
|
+
partition_wait_time=1,
|
|
59
|
+
sleep_time=sleep_time,
|
|
60
|
+
run_once_fnc=functools.partial(
|
|
61
|
+
run_once,
|
|
62
|
+
paused_rules=paused_rules,
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def run_once(
|
|
68
|
+
paused_rules: dict[str, datetime],
|
|
69
|
+
heartbeat_handler: HeartbeatHandler,
|
|
70
|
+
**_kwargs
|
|
71
|
+
) -> None:
|
|
72
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
73
|
+
|
|
74
|
+
start = time.time()
|
|
75
|
+
|
|
76
|
+
# Refresh paused rules
|
|
77
|
+
iter_paused_rules = deepcopy(paused_rules)
|
|
78
|
+
for key in iter_paused_rules:
|
|
79
|
+
if datetime.utcnow() > paused_rules[key]:
|
|
80
|
+
del paused_rules[key]
|
|
81
|
+
|
|
82
|
+
rules = get_injected_rules(total_workers=total_workers,
|
|
83
|
+
worker_number=worker_number,
|
|
84
|
+
limit=100,
|
|
85
|
+
blocked_rules=[key for key in paused_rules])
|
|
86
|
+
logger(logging.DEBUG, 'index query time %f fetch size is %d' % (time.time() - start, len(rules)))
|
|
87
|
+
|
|
88
|
+
if not rules:
|
|
89
|
+
logger(logging.DEBUG, 'did not get any work (paused_rules=%s)' % str(len(paused_rules)))
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
for rule_id in rules:
|
|
93
|
+
_, _, logger = heartbeat_handler.live()
|
|
94
|
+
logger(logging.INFO, 'Injecting rule %s' % rule_id)
|
|
95
|
+
if graceful_stop.is_set():
|
|
96
|
+
break
|
|
97
|
+
try:
|
|
98
|
+
start = time.time()
|
|
99
|
+
inject_rule(rule_id=rule_id, logger=logger)
|
|
100
|
+
logger(logging.DEBUG, 'injection of %s took %f' % (rule_id, time.time() - start))
|
|
101
|
+
except (DatabaseException, DatabaseError) as e:
|
|
102
|
+
if match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])):
|
|
103
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600)) # noqa: S311
|
|
104
|
+
METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
|
|
105
|
+
logger(logging.WARNING, 'Locks detected for %s' % rule_id)
|
|
106
|
+
elif match('.*QueuePool.*', str(e.args[0])):
|
|
107
|
+
logger(logging.WARNING, 'DatabaseException', exc_info=True)
|
|
108
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
109
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(e.args[0])):
|
|
110
|
+
logger(logging.WARNING, 'DatabaseException', exc_info=True)
|
|
111
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
112
|
+
else:
|
|
113
|
+
logger(logging.ERROR, 'DatabaseException', exc_info=True)
|
|
114
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
115
|
+
except (RSEWriteBlocked) as e:
|
|
116
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600)) # noqa: S311
|
|
117
|
+
logger(logging.WARNING, 'RSEWriteBlocked for rule %s' % rule_id)
|
|
118
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
119
|
+
except ReplicationRuleCreationTemporaryFailed as e:
|
|
120
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(60, 600)) # noqa: S311
|
|
121
|
+
logger(logging.WARNING, 'ReplicationRuleCreationTemporaryFailed for rule %s' % rule_id)
|
|
122
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
123
|
+
except RuleNotFound:
|
|
124
|
+
pass
|
|
125
|
+
except InsufficientAccountLimit:
|
|
126
|
+
# A rule with InsufficientAccountLimit on injection hangs there potentially forever
|
|
127
|
+
# It should be marked as SUSPENDED
|
|
128
|
+
logger(logging.INFO, 'Marking rule %s as SUSPENDED due to InsufficientAccountLimit' % rule_id)
|
|
129
|
+
update_rule(rule_id=rule_id, options={'state': 'SUSPENDED'})
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
133
|
+
"""
|
|
134
|
+
Graceful exit.
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
graceful_stop.set()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def run(
|
|
141
|
+
once: bool = False,
|
|
142
|
+
threads: int = 1,
|
|
143
|
+
sleep_time: int = 60
|
|
144
|
+
) -> None:
|
|
145
|
+
"""
|
|
146
|
+
Starts up the Judge-Injector threads.
|
|
147
|
+
"""
|
|
148
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
149
|
+
|
|
150
|
+
if rucio.db.sqla.util.is_old_db():
|
|
151
|
+
raise DatabaseException('Database was not updated, daemon won\'t start')
|
|
152
|
+
|
|
153
|
+
if once:
|
|
154
|
+
rule_injector(once)
|
|
155
|
+
else:
|
|
156
|
+
logging.info('Injector starting %s threads' % str(threads))
|
|
157
|
+
thread_list = [threading.Thread(target=rule_injector, kwargs={'once': once,
|
|
158
|
+
'sleep_time': sleep_time}) for i in range(0, threads)]
|
|
159
|
+
[t.start() for t in thread_list]
|
|
160
|
+
# Interruptible joins require a timeout.
|
|
161
|
+
while thread_list[0].is_alive():
|
|
162
|
+
[t.join(timeout=3.14) for t in thread_list]
|
|
@@ -0,0 +1,154 @@
|
|
|
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
|
+
Judge-Repairer is a daemon to repair stuck replication rules.
|
|
17
|
+
"""
|
|
18
|
+
import functools
|
|
19
|
+
import logging
|
|
20
|
+
import threading
|
|
21
|
+
import time
|
|
22
|
+
import traceback
|
|
23
|
+
from copy import deepcopy
|
|
24
|
+
from datetime import datetime, timedelta
|
|
25
|
+
from random import randint
|
|
26
|
+
from re import match
|
|
27
|
+
from typing import TYPE_CHECKING, Optional
|
|
28
|
+
|
|
29
|
+
from sqlalchemy.exc import DatabaseError
|
|
30
|
+
|
|
31
|
+
import rucio.db.sqla.util
|
|
32
|
+
from rucio.common import exception
|
|
33
|
+
from rucio.common.exception import DatabaseException
|
|
34
|
+
from rucio.common.logging import setup_logging
|
|
35
|
+
from rucio.core.monitor import MetricManager
|
|
36
|
+
from rucio.core.rule import get_stuck_rules, repair_rule
|
|
37
|
+
from rucio.daemons.common import HeartbeatHandler, run_daemon
|
|
38
|
+
from rucio.db.sqla.constants import ORACLE_CONNECTION_LOST_CONTACT_REGEX, ORACLE_RESOURCE_BUSY_REGEX
|
|
39
|
+
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from types import FrameType
|
|
42
|
+
|
|
43
|
+
METRICS = MetricManager(module=__name__)
|
|
44
|
+
graceful_stop = threading.Event()
|
|
45
|
+
DAEMON_NAME = 'judge-repairer'
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def rule_repairer(
|
|
49
|
+
once: bool = False,
|
|
50
|
+
sleep_time: int = 60
|
|
51
|
+
) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Main loop to check for STUCK replication rules
|
|
54
|
+
"""
|
|
55
|
+
paused_rules = {} # {rule_id: datetime}
|
|
56
|
+
run_daemon(
|
|
57
|
+
once=once,
|
|
58
|
+
graceful_stop=graceful_stop,
|
|
59
|
+
executable=DAEMON_NAME,
|
|
60
|
+
partition_wait_time=1,
|
|
61
|
+
sleep_time=sleep_time,
|
|
62
|
+
run_once_fnc=functools.partial(
|
|
63
|
+
run_once,
|
|
64
|
+
paused_rules=paused_rules,
|
|
65
|
+
delta=-1 if once else 1800,
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def run_once(
|
|
71
|
+
paused_rules: dict[str, datetime],
|
|
72
|
+
delta: int,
|
|
73
|
+
heartbeat_handler: HeartbeatHandler,
|
|
74
|
+
**_kwargs
|
|
75
|
+
) -> None:
|
|
76
|
+
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
77
|
+
|
|
78
|
+
start = time.time()
|
|
79
|
+
|
|
80
|
+
# Refresh paused rules
|
|
81
|
+
iter_paused_rules = deepcopy(paused_rules)
|
|
82
|
+
for key in iter_paused_rules:
|
|
83
|
+
if datetime.utcnow() > paused_rules[key]:
|
|
84
|
+
del paused_rules[key]
|
|
85
|
+
|
|
86
|
+
# Select a bunch of rules for this worker to repair
|
|
87
|
+
rules = get_stuck_rules(total_workers=total_workers,
|
|
88
|
+
worker_number=worker_number,
|
|
89
|
+
delta=delta,
|
|
90
|
+
limit=100,
|
|
91
|
+
blocked_rules=[key for key in paused_rules])
|
|
92
|
+
|
|
93
|
+
logger(logging.DEBUG, 'index query time %f fetch size is %d' % (time.time() - start, len(rules)))
|
|
94
|
+
|
|
95
|
+
if not rules:
|
|
96
|
+
logger(logging.DEBUG, 'did not get any work (paused_rules=%s)' % (str(len(paused_rules))))
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
for rule_id in rules:
|
|
100
|
+
_, _, logger = heartbeat_handler.live()
|
|
101
|
+
logger(logging.INFO, 'Repairing rule %s' % (rule_id))
|
|
102
|
+
if graceful_stop.is_set():
|
|
103
|
+
break
|
|
104
|
+
try:
|
|
105
|
+
start = time.time()
|
|
106
|
+
repair_rule(rule_id=rule_id)
|
|
107
|
+
logger(logging.DEBUG, 'repairing of %s took %f' % (rule_id, time.time() - start))
|
|
108
|
+
except (DatabaseException, DatabaseError) as e:
|
|
109
|
+
if match(ORACLE_RESOURCE_BUSY_REGEX, str(e.args[0])):
|
|
110
|
+
paused_rules[rule_id] = datetime.utcnow() + timedelta(seconds=randint(600, 2400)) # noqa: S311
|
|
111
|
+
logger(logging.WARNING, 'Locks detected for %s' % (rule_id))
|
|
112
|
+
METRICS.counter('exceptions.{exception}').labels(exception='LocksDetected').inc()
|
|
113
|
+
elif match('.*QueuePool.*', str(e.args[0])):
|
|
114
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
115
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
116
|
+
elif match(ORACLE_CONNECTION_LOST_CONTACT_REGEX, str(e.args[0])):
|
|
117
|
+
logger(logging.WARNING, traceback.format_exc())
|
|
118
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
119
|
+
else:
|
|
120
|
+
logger(logging.ERROR, traceback.format_exc())
|
|
121
|
+
METRICS.counter('exceptions.{exception}').labels(exception=e.__class__.__name__).inc()
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> None:
|
|
125
|
+
"""
|
|
126
|
+
Graceful exit.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
graceful_stop.set()
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def run(
|
|
133
|
+
once: bool = False,
|
|
134
|
+
threads: int = 1,
|
|
135
|
+
sleep_time: int = 60
|
|
136
|
+
) -> None:
|
|
137
|
+
"""
|
|
138
|
+
Starts up the Judge-Repairer threads.
|
|
139
|
+
"""
|
|
140
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
141
|
+
|
|
142
|
+
if rucio.db.sqla.util.is_old_db():
|
|
143
|
+
raise exception.DatabaseException('Database was not updated, daemon won\'t start')
|
|
144
|
+
|
|
145
|
+
if once:
|
|
146
|
+
rule_repairer(once)
|
|
147
|
+
else:
|
|
148
|
+
logging.info('Repairer starting %s threads' % str(threads))
|
|
149
|
+
thread_list = [threading.Thread(target=rule_repairer, kwargs={'once': once,
|
|
150
|
+
'sleep_time': sleep_time}) for i in range(0, threads)]
|
|
151
|
+
[t.start() for t in thread_list]
|
|
152
|
+
# Interruptible joins require a timeout.
|
|
153
|
+
while thread_list[0].is_alive():
|
|
154
|
+
[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.
|