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,497 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import datetime
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
import re
|
|
19
|
+
import subprocess
|
|
20
|
+
import tempfile
|
|
21
|
+
from typing import TYPE_CHECKING, Any, Optional, Union, cast
|
|
22
|
+
|
|
23
|
+
from rucio.common import dumper
|
|
24
|
+
from rucio.common.dumper import DUMPS_CACHE_DIR, data_models, error, path_parsing
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from argparse import Namespace, _SubParsersAction
|
|
28
|
+
from collections.abc import Callable, Iterable, Iterator
|
|
29
|
+
|
|
30
|
+
from _typeshed import SupportsNext
|
|
31
|
+
|
|
32
|
+
subcommands = ['consistency', 'consistency-manual']
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Consistency(data_models.DataModel):
|
|
36
|
+
SCHEMA = (
|
|
37
|
+
('apparent_status', str),
|
|
38
|
+
('path', str),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def dump(
|
|
43
|
+
cls,
|
|
44
|
+
subcommand: str,
|
|
45
|
+
ddm_endpoint: str,
|
|
46
|
+
storage_dump: str,
|
|
47
|
+
prev_date_fname: Optional[str] = None,
|
|
48
|
+
next_date_fname: Optional[str] = None,
|
|
49
|
+
prev_date: Optional[Union[str, datetime.datetime]] = None,
|
|
50
|
+
next_date: Optional[Union[str, datetime.datetime]] = None,
|
|
51
|
+
sort_rucio_replica_dumps: bool = True,
|
|
52
|
+
date: Optional[datetime.datetime] = None,
|
|
53
|
+
cache_dir: str = DUMPS_CACHE_DIR
|
|
54
|
+
):
|
|
55
|
+
logger = logging.getLogger('auditor.consistency')
|
|
56
|
+
if subcommand == 'consistency':
|
|
57
|
+
if prev_date is None:
|
|
58
|
+
prev_date = 'latest'
|
|
59
|
+
if next_date is None:
|
|
60
|
+
next_date = 'latest'
|
|
61
|
+
prev_date_fname = data_models.Replica.download(
|
|
62
|
+
ddm_endpoint, prev_date, cache_dir=cache_dir)
|
|
63
|
+
next_date_fname = data_models.Replica.download(
|
|
64
|
+
ddm_endpoint, next_date, cache_dir=cache_dir)
|
|
65
|
+
if (prev_date_fname is None) or (next_date_fname is None):
|
|
66
|
+
raise ValueError("Both prev_date_fname and next_date_fname are required for subcommand='consistency'; found prev_data_fname=%s and next_date_fname=%s" % (prev_date_fname, next_date_fname))
|
|
67
|
+
elif subcommand == 'consistency-manual':
|
|
68
|
+
pass
|
|
69
|
+
else:
|
|
70
|
+
raise ValueError("subcommand %s not accepted, choice from ('consistency','consistency-manual')" % subcommand)
|
|
71
|
+
|
|
72
|
+
prefix_components = path_parsing.components(dumper.ddmendpoint_url(ddm_endpoint))
|
|
73
|
+
|
|
74
|
+
def parser(line: str) -> str:
|
|
75
|
+
'''
|
|
76
|
+
Simple parser for Rucio replica dumps.
|
|
77
|
+
|
|
78
|
+
:param line: String with one line of a dump.
|
|
79
|
+
:returns: A tuple with the path and status of the replica.
|
|
80
|
+
'''
|
|
81
|
+
fields = line.split('\t')
|
|
82
|
+
path = fields[6].strip().lstrip('/')
|
|
83
|
+
status = fields[8].strip()
|
|
84
|
+
|
|
85
|
+
return ','.join((path, status))
|
|
86
|
+
|
|
87
|
+
def strip_storage_dump(line: str) -> str:
|
|
88
|
+
'''
|
|
89
|
+
Parser to have consistent paths in storage dumps.
|
|
90
|
+
|
|
91
|
+
:param line: String with one line of a dump.
|
|
92
|
+
:returns: Path formatted as in the Rucio Replica Dumps.
|
|
93
|
+
'''
|
|
94
|
+
relative = path_parsing.remove_prefix(
|
|
95
|
+
prefix_components,
|
|
96
|
+
path_parsing.components(line),
|
|
97
|
+
)
|
|
98
|
+
if relative[0] == 'rucio':
|
|
99
|
+
relative = relative[1:]
|
|
100
|
+
return '/'.join(relative)
|
|
101
|
+
|
|
102
|
+
if sort_rucio_replica_dumps:
|
|
103
|
+
prev_date_fname_sorted = gnu_sort(
|
|
104
|
+
parse_and_filter_file(prev_date_fname, parser=parser, cache_dir=cache_dir), # type: ignore
|
|
105
|
+
delimiter=',',
|
|
106
|
+
fieldspec='1',
|
|
107
|
+
cache_dir=cache_dir,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
next_date_fname_sorted = gnu_sort(
|
|
111
|
+
parse_and_filter_file(next_date_fname, parser=parser, cache_dir=cache_dir), # type: ignore
|
|
112
|
+
delimiter=',',
|
|
113
|
+
fieldspec='1',
|
|
114
|
+
cache_dir=cache_dir,
|
|
115
|
+
)
|
|
116
|
+
else:
|
|
117
|
+
prev_date_fname_sorted = parse_and_filter_file(
|
|
118
|
+
prev_date_fname, # type: ignore
|
|
119
|
+
parser=parser,
|
|
120
|
+
cache_dir=cache_dir,
|
|
121
|
+
)
|
|
122
|
+
next_date_fname_sorted = parse_and_filter_file(
|
|
123
|
+
next_date_fname, # type: ignore
|
|
124
|
+
parser=parser,
|
|
125
|
+
cache_dir=cache_dir,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
standard_name_re = r'(ddmendpoint_{0}_\d{{2}}-\d{{2}}-\d{{4}}_[0-9a-f]{{40}})$'.format(ddm_endpoint)
|
|
129
|
+
standard_name_match = re.search(standard_name_re, storage_dump)
|
|
130
|
+
if standard_name_match is not None:
|
|
131
|
+
# If the original filename was generated using the expected format,
|
|
132
|
+
# just use the name as prefix for the parsed file.
|
|
133
|
+
sd_prefix = standard_name_match.group(0)
|
|
134
|
+
elif date is not None:
|
|
135
|
+
# Otherwise try to use the date information and DDMEndpoint name to
|
|
136
|
+
# have a meaningful filename.
|
|
137
|
+
sd_prefix = 'ddmendpoint_{0}_{1}'.format(
|
|
138
|
+
ddm_endpoint,
|
|
139
|
+
date.strftime('%d-%m-%Y'),
|
|
140
|
+
)
|
|
141
|
+
else:
|
|
142
|
+
# As last resort use only the DDMEndpoint name, but this is error
|
|
143
|
+
# prone as old dumps may interfere with the checks.
|
|
144
|
+
sd_prefix = 'ddmendpoint_{0}_unknown_date'.format(
|
|
145
|
+
ddm_endpoint,
|
|
146
|
+
)
|
|
147
|
+
logger.warning(
|
|
148
|
+
'Using basic and error prune naming for RSE dump as no date '
|
|
149
|
+
'information was provided, %s dump will be named %s',
|
|
150
|
+
ddm_endpoint,
|
|
151
|
+
sd_prefix,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
storage_dump_fname_sorted = gnu_sort(
|
|
155
|
+
parse_and_filter_file(
|
|
156
|
+
storage_dump,
|
|
157
|
+
parser=strip_storage_dump,
|
|
158
|
+
prefix=sd_prefix,
|
|
159
|
+
cache_dir=cache_dir,
|
|
160
|
+
),
|
|
161
|
+
prefix=sd_prefix,
|
|
162
|
+
cache_dir=cache_dir,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
with open(prev_date_fname_sorted) as prevf:
|
|
166
|
+
with open(next_date_fname_sorted) as nextf:
|
|
167
|
+
with open(storage_dump_fname_sorted) as sdump:
|
|
168
|
+
for path, where, status in compare3(prevf, sdump, nextf):
|
|
169
|
+
prevstatus, nextstatus = status
|
|
170
|
+
|
|
171
|
+
if where[0] and not where[1] and where[2]:
|
|
172
|
+
if prevstatus == 'A' and nextstatus == 'A':
|
|
173
|
+
yield cls('LOST', path)
|
|
174
|
+
|
|
175
|
+
if not where[0] and where[1] and not where[2]:
|
|
176
|
+
yield cls('DARK', path)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _try_to_advance(
|
|
180
|
+
it: 'SupportsNext[str]',
|
|
181
|
+
default: Optional[str] = None
|
|
182
|
+
) -> Optional[str]:
|
|
183
|
+
try:
|
|
184
|
+
el = next(it)
|
|
185
|
+
except StopIteration:
|
|
186
|
+
return default
|
|
187
|
+
return el.strip()
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def min_value(*values: Optional[str]) -> str:
|
|
191
|
+
'''
|
|
192
|
+
Minimum between the input values, ignoring None
|
|
193
|
+
'''
|
|
194
|
+
values_without_none = cast('list[str]', [value for value in values if value is not None])
|
|
195
|
+
if len(values_without_none) == 0:
|
|
196
|
+
raise ValueError("Input contains 0 non-null values.")
|
|
197
|
+
return min(values_without_none)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def split_if_not_none(
|
|
201
|
+
value: Optional[str],
|
|
202
|
+
sep: str = ',',
|
|
203
|
+
fields: int = 2
|
|
204
|
+
) -> Union[str, list]:
|
|
205
|
+
return value.split(sep) if value is not None else ([None] * fields)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def compare3(
|
|
209
|
+
it0: 'Iterable[str]',
|
|
210
|
+
it1: 'Iterable[str]',
|
|
211
|
+
it2: 'Iterable[str]'
|
|
212
|
+
) -> 'Iterator[tuple[str, tuple[bool, bool, bool], tuple[Optional[str], Optional[str]]]]':
|
|
213
|
+
'''
|
|
214
|
+
Generator to compare 3 sorted iterables, in each
|
|
215
|
+
iteration it yields a tuple of the form (current, (bool, bool, bool))
|
|
216
|
+
where current is the current element checked and the
|
|
217
|
+
second element of the tuple is a triplet whose elements take
|
|
218
|
+
a true value if current is contained in the it0, it1 or it2
|
|
219
|
+
respectively.
|
|
220
|
+
|
|
221
|
+
This function can't compare the iterators properly if None is
|
|
222
|
+
a valid value.
|
|
223
|
+
'''
|
|
224
|
+
|
|
225
|
+
it0 = iter(it0)
|
|
226
|
+
it1 = iter(it1)
|
|
227
|
+
it2 = iter(it2)
|
|
228
|
+
v0 = _try_to_advance(it0)
|
|
229
|
+
v1 = _try_to_advance(it1)
|
|
230
|
+
v2 = _try_to_advance(it2)
|
|
231
|
+
|
|
232
|
+
while v0 is not None or v1 is not None or v2 is not None:
|
|
233
|
+
path0, status0 = split_if_not_none(v0)
|
|
234
|
+
path2, status2 = split_if_not_none(v2)
|
|
235
|
+
|
|
236
|
+
vmin = min_value(path0, v1, path2)
|
|
237
|
+
in0 = in1 = in2 = False
|
|
238
|
+
in0_status = in2_status = None
|
|
239
|
+
|
|
240
|
+
# Detect in which iterables the value is present
|
|
241
|
+
# inN is True if the value is present on the N iterable.
|
|
242
|
+
# sN is the status of the path in the rucio replica
|
|
243
|
+
# dumps (N is either 0 or 2).
|
|
244
|
+
if path0 is not None and path0 == vmin:
|
|
245
|
+
in0 = True
|
|
246
|
+
in0_status = status0
|
|
247
|
+
|
|
248
|
+
if v1 is not None and v1 == vmin:
|
|
249
|
+
in1 = True
|
|
250
|
+
|
|
251
|
+
if path2 is not None and path2 == vmin:
|
|
252
|
+
in2 = True
|
|
253
|
+
in2_status = status2
|
|
254
|
+
|
|
255
|
+
# yield the value, in which iterables is present, and the status
|
|
256
|
+
# in each rucio replica dumps (if it is present there, else None).
|
|
257
|
+
yield (vmin, (in0, in1, in2), (in0_status, in2_status))
|
|
258
|
+
|
|
259
|
+
# Discard duplicate entries (it shouldn't be duplicate entries
|
|
260
|
+
# anyways) and
|
|
261
|
+
# advance the iterators, if the iterator N is depleted vN is set
|
|
262
|
+
# to None.
|
|
263
|
+
while v0 is not None and path0 == vmin:
|
|
264
|
+
v0 = _try_to_advance(it0)
|
|
265
|
+
path0, status0 = split_if_not_none(v0)
|
|
266
|
+
|
|
267
|
+
while v1 is not None and v1 == vmin:
|
|
268
|
+
v1 = _try_to_advance(it1)
|
|
269
|
+
|
|
270
|
+
while v2 is not None and path2 == vmin:
|
|
271
|
+
v2 = _try_to_advance(it2)
|
|
272
|
+
path2, status2 = split_if_not_none(v2)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def parse_and_filter_file(
|
|
276
|
+
filepath: str,
|
|
277
|
+
parser: 'Callable' = lambda s: s,
|
|
278
|
+
filter_: 'Callable' = lambda s: s,
|
|
279
|
+
prefix: Optional[str] = None,
|
|
280
|
+
postfix: str = 'parsed',
|
|
281
|
+
cache_dir: str = DUMPS_CACHE_DIR
|
|
282
|
+
) -> str:
|
|
283
|
+
'''
|
|
284
|
+
Opens `filepath` as a read-only file, and for each line of the file
|
|
285
|
+
for which the `filter_` function returns True, it writes a version
|
|
286
|
+
parsed with the `parser` function.
|
|
287
|
+
|
|
288
|
+
The name of the output file is generated appending '_' + `postfix` to
|
|
289
|
+
the filename in `filepath`. If `prefix` is given it is used instead
|
|
290
|
+
of `filepath`.
|
|
291
|
+
|
|
292
|
+
The output file (and temporary files while processing are stored in
|
|
293
|
+
`cache_dir`.
|
|
294
|
+
|
|
295
|
+
Default values for the arguments:
|
|
296
|
+
- `parser`: returns the same string.
|
|
297
|
+
- `filter_`: returns True for any argument.
|
|
298
|
+
- `prefix`: None (the name of the input file is used as prefix).
|
|
299
|
+
- `postfix`: 'parsed'.
|
|
300
|
+
- `cache_dir`: DUMPS_CACHE_DIR.
|
|
301
|
+
|
|
302
|
+
The output file is created with a random name and renamed atomically
|
|
303
|
+
when it is complete.
|
|
304
|
+
|
|
305
|
+
'\n' is appended to each line, therefore if the input is 'a\nb\n' and `parser`
|
|
306
|
+
is not especified the output will be 'a\n\nb\n\n'
|
|
307
|
+
'''
|
|
308
|
+
|
|
309
|
+
prefix = os.path.basename(filepath) if prefix is None else prefix
|
|
310
|
+
output_name = '_'.join((prefix, postfix))
|
|
311
|
+
output_path = os.path.join(cache_dir, output_name)
|
|
312
|
+
|
|
313
|
+
if os.path.exists(output_path):
|
|
314
|
+
return output_path
|
|
315
|
+
|
|
316
|
+
with dumper.temp_file(cache_dir, final_name=output_name) as (output, _):
|
|
317
|
+
input_ = dumper.smart_open(filepath)
|
|
318
|
+
if input_ is not None:
|
|
319
|
+
for line in input_:
|
|
320
|
+
if filter_(line):
|
|
321
|
+
output.write(parser(line) + '\n')
|
|
322
|
+
|
|
323
|
+
input_.close()
|
|
324
|
+
|
|
325
|
+
return output_path
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def gnu_sort(
|
|
329
|
+
file_path: str,
|
|
330
|
+
prefix: Optional[str] = None,
|
|
331
|
+
delimiter: Optional[str] = None,
|
|
332
|
+
fieldspec: Optional[str] = None,
|
|
333
|
+
cache_dir: str = DUMPS_CACHE_DIR
|
|
334
|
+
) -> str:
|
|
335
|
+
'''
|
|
336
|
+
Sort the file with path `file_path` using the GNU sort command, the
|
|
337
|
+
original file is unchanged, the output file is saved with path
|
|
338
|
+
<cache_dir>/<prefix>_sorted.
|
|
339
|
+
|
|
340
|
+
:param prefix: If given the output file will be named <prefix>_sorted.
|
|
341
|
+
Otherwise the prefix is the name of the input file.
|
|
342
|
+
:param delimiter: Delimiter character if the data is formatted in
|
|
343
|
+
columns (argument of -t in the sort command).
|
|
344
|
+
:param fieldspec: String with the specification of column or columns
|
|
345
|
+
to be used to sort (argument -k in the sort command).
|
|
346
|
+
:param cachedir: Working dir where the output file will be placed.
|
|
347
|
+
|
|
348
|
+
Note: Using GNU sort to sort large files is convenient as it has low
|
|
349
|
+
memory and it is relatively fast if used with the environment variable
|
|
350
|
+
LC_ALL set to C as in this function.
|
|
351
|
+
'''
|
|
352
|
+
if (delimiter is not None) ^ (fieldspec is not None):
|
|
353
|
+
raise ValueError("Either both delimiter and fieldspec is set, or neither are.")
|
|
354
|
+
if delimiter is None:
|
|
355
|
+
cmd_line = 'LC_ALL=C sort {0} > {1}'
|
|
356
|
+
else:
|
|
357
|
+
cmd_line = 'LC_ALL=C sort -t {0} -k {1} {{0}} > {{1}}'.format(delimiter, fieldspec)
|
|
358
|
+
|
|
359
|
+
prefix = os.path.basename(file_path) if prefix is None else prefix
|
|
360
|
+
|
|
361
|
+
sorted_name = '_'.join((prefix, 'sorted'))
|
|
362
|
+
sorted_path = os.path.join(cache_dir, sorted_name)
|
|
363
|
+
|
|
364
|
+
if os.path.exists(sorted_path):
|
|
365
|
+
return sorted_path
|
|
366
|
+
|
|
367
|
+
tfile = tempfile.NamedTemporaryFile(dir=cache_dir, delete=False)
|
|
368
|
+
|
|
369
|
+
subprocess.check_call(
|
|
370
|
+
cmd_line.format(file_path, tfile.name),
|
|
371
|
+
shell=True,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
os.link(tfile.name, sorted_path)
|
|
375
|
+
os.unlink(tfile.name)
|
|
376
|
+
|
|
377
|
+
return sorted_path
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def populate_args(argparser: '_SubParsersAction') -> None:
|
|
381
|
+
# Option to download the rucio replica dumps automatically
|
|
382
|
+
parser = argparser.add_parser(
|
|
383
|
+
'consistency',
|
|
384
|
+
help='Consistency check to verify possible lost files and dark data '
|
|
385
|
+
'(replica dumps are downloaded automatically)'
|
|
386
|
+
)
|
|
387
|
+
parser.add_argument('ddm_endpoint')
|
|
388
|
+
parser.add_argument('storage_dump')
|
|
389
|
+
parser.add_argument(
|
|
390
|
+
'--delta',
|
|
391
|
+
help='Difference in days between the SE dump and the desired rucio '
|
|
392
|
+
'replica dumps (use either this argument or --prev-date and '
|
|
393
|
+
'--next-date)',
|
|
394
|
+
required=False
|
|
395
|
+
)
|
|
396
|
+
parser.add_argument(
|
|
397
|
+
'--prev-date',
|
|
398
|
+
help='Date of the older rucio replica dump to use',
|
|
399
|
+
required=False
|
|
400
|
+
)
|
|
401
|
+
parser.add_argument(
|
|
402
|
+
'--next-date',
|
|
403
|
+
help='Date of the newer rucio replica dump to use',
|
|
404
|
+
required=False
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
# Option to use already downloaded rucio replica dumps
|
|
408
|
+
parser_manual = argparser.add_parser(
|
|
409
|
+
'consistency-manual',
|
|
410
|
+
help='Consistency check to verify possible lost files and dark data '
|
|
411
|
+
'(replica dumps should be provided by the user)'
|
|
412
|
+
)
|
|
413
|
+
parser_manual.add_argument('ddm_endpoint')
|
|
414
|
+
parser_manual.add_argument('replicas_before')
|
|
415
|
+
parser_manual.add_argument('storage_dump')
|
|
416
|
+
parser_manual.add_argument('replicas_after')
|
|
417
|
+
|
|
418
|
+
for p in (parser, parser_manual):
|
|
419
|
+
p.add_argument(
|
|
420
|
+
'--sort-rucio-dumps',
|
|
421
|
+
help='Starting 18-08-2015 the Rucio Replica Dumps are sorted by '
|
|
422
|
+
'path. If you need to work with older dumps use this '
|
|
423
|
+
'argument.',
|
|
424
|
+
action='store_true'
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
_date_re = re.compile(r'dump_(\d{8})')
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def _parse_args_consistency(args: 'Namespace') -> dict[str, datetime.datetime]:
|
|
432
|
+
args_dict = {}
|
|
433
|
+
|
|
434
|
+
# Filename should contain the date
|
|
435
|
+
date_str = _date_re.match(os.path.basename(args.storage_dump))
|
|
436
|
+
if date_str is None:
|
|
437
|
+
error('The storage dump filename must be of the form '
|
|
438
|
+
'"dump_YYYYMMDD" where the date correspond to the date '
|
|
439
|
+
'of the newest files included')
|
|
440
|
+
else:
|
|
441
|
+
date_str = date_str.group(1)
|
|
442
|
+
if date_str is None:
|
|
443
|
+
error('Invalid date {0}'.format(date_str))
|
|
444
|
+
try:
|
|
445
|
+
args_dict['date'] = date = datetime.datetime.strptime(date_str, '%Y%m%d')
|
|
446
|
+
except ValueError:
|
|
447
|
+
error('Invalid date {0}'.format(date_str))
|
|
448
|
+
|
|
449
|
+
if not os.path.exists(args.storage_dump):
|
|
450
|
+
error('File "{0}" does not exist'.format(args.storage_dump))
|
|
451
|
+
|
|
452
|
+
if (args.prev_date is not None or args.next_date is not None) and args.delta is not None:
|
|
453
|
+
error('Missing or conflicting arguments, specify either '
|
|
454
|
+
'"--delta" or "--prev-date" and "--next-date"')
|
|
455
|
+
|
|
456
|
+
if args.prev_date is not None and args.next_date is not None:
|
|
457
|
+
args_dict['prev_date'] = datetime.datetime.strptime(
|
|
458
|
+
args.prev_date, '%d-%m-%Y',
|
|
459
|
+
)
|
|
460
|
+
args_dict['next_date'] = datetime.datetime.strptime(
|
|
461
|
+
args.next_date, '%d-%m-%Y',
|
|
462
|
+
)
|
|
463
|
+
elif args.delta is not None:
|
|
464
|
+
delta = int(args.delta)
|
|
465
|
+
args_dict['prev_date'] = date - datetime.timedelta(days=delta)
|
|
466
|
+
args_dict['next_date'] = date + datetime.timedelta(days=delta)
|
|
467
|
+
else:
|
|
468
|
+
error('Missing arguments, specify either "--delta" or '
|
|
469
|
+
'"--prev-date" and "--next-date"')
|
|
470
|
+
|
|
471
|
+
return args_dict
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def _parse_args_consistency_manual(args: 'Namespace') -> dict[str, Any]:
|
|
475
|
+
args_dict = {}
|
|
476
|
+
args_dict['prev_date_fname'] = args.replicas_before
|
|
477
|
+
args_dict['next_date_fname'] = args.replicas_after
|
|
478
|
+
|
|
479
|
+
for path in (args.storage_dump, args_dict['prev_date_fname'], args_dict['next_date_fname']):
|
|
480
|
+
if not os.path.exists(path):
|
|
481
|
+
error('File "{0}" does not exist'.format(path))
|
|
482
|
+
|
|
483
|
+
return args_dict
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
def parse_args(args: 'Namespace') -> dict[str, Any]:
|
|
487
|
+
args_dict = {}
|
|
488
|
+
args_dict['subcommand'] = args.subcommand
|
|
489
|
+
args_dict['ddm_endpoint'] = args.ddm_endpoint
|
|
490
|
+
args_dict['storage_dump'] = args.storage_dump
|
|
491
|
+
args_dict['sort_rucio_replica_dumps'] = args.sort_rucio_dumps
|
|
492
|
+
if args.subcommand == 'consistency':
|
|
493
|
+
args_dict.update(_parse_args_consistency(args))
|
|
494
|
+
else:
|
|
495
|
+
args_dict.update(_parse_args_consistency_manual(args))
|
|
496
|
+
|
|
497
|
+
return args_dict
|