rucio 35.7.0__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/client/__init__.py +15 -0
- rucio/client/accountclient.py +433 -0
- rucio/client/accountlimitclient.py +183 -0
- rucio/client/baseclient.py +974 -0
- rucio/client/client.py +76 -0
- rucio/client/configclient.py +126 -0
- rucio/client/credentialclient.py +59 -0
- rucio/client/didclient.py +866 -0
- rucio/client/diracclient.py +56 -0
- rucio/client/downloadclient.py +1785 -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 +454 -0
- rucio/client/requestclient.py +125 -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 +955 -0
- rucio/common/__init__.py +13 -0
- rucio/common/cache.py +74 -0
- rucio/common/config.py +801 -0
- rucio/common/constants.py +159 -0
- rucio/common/constraints.py +17 -0
- rucio/common/didtype.py +189 -0
- rucio/common/dumper/__init__.py +335 -0
- rucio/common/dumper/consistency.py +452 -0
- rucio/common/dumper/data_models.py +318 -0
- rucio/common/dumper/path_parsing.py +64 -0
- rucio/common/exception.py +1151 -0
- rucio/common/extra.py +36 -0
- rucio/common/logging.py +420 -0
- rucio/common/pcache.py +1408 -0
- rucio/common/plugins.py +153 -0
- rucio/common/policy.py +84 -0
- rucio/common/schema/__init__.py +150 -0
- rucio/common/schema/atlas.py +413 -0
- rucio/common/schema/belleii.py +408 -0
- rucio/common/schema/domatpc.py +401 -0
- rucio/common/schema/escape.py +426 -0
- rucio/common/schema/generic.py +433 -0
- rucio/common/schema/generic_multi_vo.py +412 -0
- rucio/common/schema/icecube.py +406 -0
- rucio/common/stomp_utils.py +159 -0
- rucio/common/stopwatch.py +55 -0
- rucio/common/test_rucio_server.py +148 -0
- rucio/common/types.py +403 -0
- rucio/common/utils.py +2238 -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 +423 -0
- rucio/core/authentication.py +620 -0
- rucio/core/config.py +456 -0
- rucio/core/credential.py +225 -0
- rucio/core/did.py +3000 -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/filter_engine.py +613 -0
- rucio/core/did_meta_plugins/json_meta.py +240 -0
- rucio/core/did_meta_plugins/mongo_meta.py +216 -0
- rucio/core/did_meta_plugins/postgres_meta.py +316 -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 +300 -0
- rucio/core/importer.py +259 -0
- rucio/core/lifetime_exception.py +377 -0
- rucio/core/lock.py +576 -0
- rucio/core/message.py +282 -0
- rucio/core/meta_conventions.py +203 -0
- rucio/core/monitor.py +447 -0
- rucio/core/naming_convention.py +195 -0
- rucio/core/nongrid_trace.py +136 -0
- rucio/core/oidc.py +1461 -0
- rucio/core/permission/__init__.py +119 -0
- rucio/core/permission/atlas.py +1348 -0
- rucio/core/permission/belleii.py +1077 -0
- rucio/core/permission/escape.py +1078 -0
- rucio/core/permission/generic.py +1130 -0
- rucio/core/permission/generic_multi_vo.py +1150 -0
- rucio/core/quarantined_replica.py +223 -0
- rucio/core/replica.py +4158 -0
- rucio/core/replica_sorter.py +366 -0
- rucio/core/request.py +3089 -0
- rucio/core/rse.py +1875 -0
- rucio/core/rse_counter.py +186 -0
- rucio/core/rse_expression_parser.py +459 -0
- rucio/core/rse_selector.py +302 -0
- rucio/core/rule.py +4483 -0
- rucio/core/rule_grouping.py +1618 -0
- rucio/core/scope.py +180 -0
- rucio/core/subscription.py +364 -0
- rucio/core/topology.py +490 -0
- rucio/core/trace.py +375 -0
- rucio/core/transfer.py +1517 -0
- rucio/core/vo.py +169 -0
- rucio/core/volatile_replica.py +150 -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 +293 -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/c3po/__init__.py +13 -0
- rucio/daemons/c3po/algorithms/__init__.py +13 -0
- rucio/daemons/c3po/algorithms/simple.py +134 -0
- rucio/daemons/c3po/algorithms/t2_free_space.py +128 -0
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +130 -0
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +294 -0
- rucio/daemons/c3po/c3po.py +371 -0
- rucio/daemons/c3po/collectors/__init__.py +13 -0
- rucio/daemons/c3po/collectors/agis.py +108 -0
- rucio/daemons/c3po/collectors/free_space.py +81 -0
- rucio/daemons/c3po/collectors/jedi_did.py +57 -0
- rucio/daemons/c3po/collectors/mock_did.py +51 -0
- rucio/daemons/c3po/collectors/network_metrics.py +71 -0
- rucio/daemons/c3po/collectors/workload.py +112 -0
- rucio/daemons/c3po/utils/__init__.py +13 -0
- rucio/daemons/c3po/utils/dataset_cache.py +50 -0
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +56 -0
- rucio/daemons/c3po/utils/expiring_list.py +62 -0
- rucio/daemons/c3po/utils/popularity.py +85 -0
- rucio/daemons/c3po/utils/timeseries.py +89 -0
- rucio/daemons/cache/__init__.py +13 -0
- rucio/daemons/cache/consumer.py +197 -0
- rucio/daemons/common.py +415 -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 +404 -0
- rucio/daemons/conveyor/preparer.py +205 -0
- rucio/daemons/conveyor/receiver.py +249 -0
- rucio/daemons/conveyor/stager.py +132 -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 +774 -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 +278 -0
- rucio/daemons/reaper/reaper.py +743 -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 +451 -0
- rucio/daemons/rsedecommissioner/profiles/types.py +92 -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 +846 -0
- rucio/daemons/tracer/__init__.py +13 -0
- rucio/daemons/tracer/kronos.py +536 -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 +201 -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/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 +1740 -0
- rucio/db/sqla/sautils.py +55 -0
- rucio/db/sqla/session.py +498 -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 +339 -0
- rucio/gateway/account_limit.py +286 -0
- rucio/gateway/authentication.py +375 -0
- rucio/gateway/config.py +217 -0
- rucio/gateway/credential.py +71 -0
- rucio/gateway/did.py +970 -0
- rucio/gateway/dirac.py +81 -0
- rucio/gateway/exporter.py +59 -0
- rucio/gateway/heartbeat.py +74 -0
- rucio/gateway/identity.py +204 -0
- rucio/gateway/importer.py +45 -0
- rucio/gateway/lifetime_exception.py +120 -0
- rucio/gateway/lock.py +153 -0
- rucio/gateway/meta_conventions.py +87 -0
- rucio/gateway/permission.py +71 -0
- rucio/gateway/quarantined_replica.py +78 -0
- rucio/gateway/replica.py +529 -0
- rucio/gateway/request.py +321 -0
- rucio/gateway/rse.py +600 -0
- rucio/gateway/rule.py +417 -0
- rucio/gateway/scope.py +99 -0
- rucio/gateway/subscription.py +277 -0
- rucio/gateway/vo.py +122 -0
- rucio/rse/__init__.py +96 -0
- rucio/rse/protocols/__init__.py +13 -0
- rucio/rse/protocols/bittorrent.py +184 -0
- rucio/rse/protocols/cache.py +122 -0
- rucio/rse/protocols/dummy.py +111 -0
- rucio/rse/protocols/gfal.py +703 -0
- rucio/rse/protocols/globus.py +243 -0
- rucio/rse/protocols/gsiftp.py +92 -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 +594 -0
- rucio/rse/protocols/rclone.py +364 -0
- rucio/rse/protocols/rfio.py +136 -0
- rucio/rse/protocols/srm.py +338 -0
- rucio/rse/protocols/ssh.py +413 -0
- rucio/rse/protocols/storm.py +206 -0
- rucio/rse/protocols/webdav.py +550 -0
- rucio/rse/protocols/xrootd.py +301 -0
- rucio/rse/rsemanager.py +764 -0
- rucio/tests/__init__.py +13 -0
- rucio/tests/common.py +270 -0
- rucio/tests/common_server.py +132 -0
- rucio/transfertool/__init__.py +13 -0
- rucio/transfertool/bittorrent.py +199 -0
- rucio/transfertool/bittorrent_driver.py +52 -0
- rucio/transfertool/bittorrent_driver_qbittorrent.py +133 -0
- rucio/transfertool/fts3.py +1596 -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 +90 -0
- rucio/transfertool/transfertool.py +221 -0
- rucio/vcsversion.py +11 -0
- rucio/version.py +38 -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 +1089 -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 +212 -0
- rucio/web/rest/flaskapi/v1/dids.py +2334 -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 +261 -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 +365 -0
- rucio/web/rest/flaskapi/v1/replicas.py +1890 -0
- rucio/web/rest/flaskapi/v1/requests.py +998 -0
- rucio/web/rest/flaskapi/v1/rses.py +2239 -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 +100 -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-35.7.0.data/data/rucio/etc/alembic.ini.template +71 -0
- rucio-35.7.0.data/data/rucio/etc/alembic_offline.ini.template +74 -0
- rucio-35.7.0.data/data/rucio/etc/globus-config.yml.template +5 -0
- rucio-35.7.0.data/data/rucio/etc/ldap.cfg.template +30 -0
- rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
- rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
- rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
- rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
- rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
- rucio-35.7.0.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
- rucio-35.7.0.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
- rucio-35.7.0.data/data/rucio/etc/rucio.cfg.atlas.client.template +42 -0
- rucio-35.7.0.data/data/rucio/etc/rucio.cfg.template +257 -0
- rucio-35.7.0.data/data/rucio/etc/rucio_multi_vo.cfg.template +234 -0
- rucio-35.7.0.data/data/rucio/requirements.server.txt +268 -0
- rucio-35.7.0.data/data/rucio/tools/bootstrap.py +34 -0
- rucio-35.7.0.data/data/rucio/tools/merge_rucio_configs.py +144 -0
- rucio-35.7.0.data/data/rucio/tools/reset_database.py +40 -0
- rucio-35.7.0.data/scripts/rucio +2542 -0
- rucio-35.7.0.data/scripts/rucio-abacus-account +74 -0
- rucio-35.7.0.data/scripts/rucio-abacus-collection-replica +46 -0
- rucio-35.7.0.data/scripts/rucio-abacus-rse +78 -0
- rucio-35.7.0.data/scripts/rucio-admin +2447 -0
- rucio-35.7.0.data/scripts/rucio-atropos +60 -0
- rucio-35.7.0.data/scripts/rucio-auditor +205 -0
- rucio-35.7.0.data/scripts/rucio-automatix +50 -0
- rucio-35.7.0.data/scripts/rucio-bb8 +57 -0
- rucio-35.7.0.data/scripts/rucio-c3po +85 -0
- rucio-35.7.0.data/scripts/rucio-cache-client +134 -0
- rucio-35.7.0.data/scripts/rucio-cache-consumer +42 -0
- rucio-35.7.0.data/scripts/rucio-conveyor-finisher +58 -0
- rucio-35.7.0.data/scripts/rucio-conveyor-poller +66 -0
- rucio-35.7.0.data/scripts/rucio-conveyor-preparer +37 -0
- rucio-35.7.0.data/scripts/rucio-conveyor-receiver +43 -0
- rucio-35.7.0.data/scripts/rucio-conveyor-stager +76 -0
- rucio-35.7.0.data/scripts/rucio-conveyor-submitter +139 -0
- rucio-35.7.0.data/scripts/rucio-conveyor-throttler +104 -0
- rucio-35.7.0.data/scripts/rucio-dark-reaper +53 -0
- rucio-35.7.0.data/scripts/rucio-dumper +160 -0
- rucio-35.7.0.data/scripts/rucio-follower +44 -0
- rucio-35.7.0.data/scripts/rucio-hermes +54 -0
- rucio-35.7.0.data/scripts/rucio-judge-cleaner +89 -0
- rucio-35.7.0.data/scripts/rucio-judge-evaluator +137 -0
- rucio-35.7.0.data/scripts/rucio-judge-injector +44 -0
- rucio-35.7.0.data/scripts/rucio-judge-repairer +44 -0
- rucio-35.7.0.data/scripts/rucio-kronos +43 -0
- rucio-35.7.0.data/scripts/rucio-minos +53 -0
- rucio-35.7.0.data/scripts/rucio-minos-temporary-expiration +50 -0
- rucio-35.7.0.data/scripts/rucio-necromancer +120 -0
- rucio-35.7.0.data/scripts/rucio-oauth-manager +63 -0
- rucio-35.7.0.data/scripts/rucio-reaper +83 -0
- rucio-35.7.0.data/scripts/rucio-replica-recoverer +248 -0
- rucio-35.7.0.data/scripts/rucio-rse-decommissioner +66 -0
- rucio-35.7.0.data/scripts/rucio-storage-consistency-actions +74 -0
- rucio-35.7.0.data/scripts/rucio-transmogrifier +77 -0
- rucio-35.7.0.data/scripts/rucio-undertaker +76 -0
- rucio-35.7.0.dist-info/METADATA +72 -0
- rucio-35.7.0.dist-info/RECORD +493 -0
- rucio-35.7.0.dist-info/WHEEL +5 -0
- rucio-35.7.0.dist-info/licenses/AUTHORS.rst +97 -0
- rucio-35.7.0.dist-info/licenses/LICENSE +201 -0
- rucio-35.7.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,371 @@
|
|
|
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
|
+
Dynamic data placement daemon.
|
|
17
|
+
'''
|
|
18
|
+
|
|
19
|
+
import logging
|
|
20
|
+
from datetime import datetime
|
|
21
|
+
from hashlib import md5
|
|
22
|
+
from json import dumps
|
|
23
|
+
from queue import Queue
|
|
24
|
+
from threading import Event, Thread
|
|
25
|
+
from time import sleep
|
|
26
|
+
from typing import TYPE_CHECKING, Optional
|
|
27
|
+
from uuid import uuid4
|
|
28
|
+
|
|
29
|
+
from requests import post
|
|
30
|
+
from requests.auth import HTTPBasicAuth
|
|
31
|
+
from requests.exceptions import RequestException
|
|
32
|
+
|
|
33
|
+
import rucio.db.sqla.util
|
|
34
|
+
from rucio.client import Client
|
|
35
|
+
from rucio.common import exception
|
|
36
|
+
from rucio.common.config import config_get, config_get_options
|
|
37
|
+
from rucio.common.logging import setup_logging
|
|
38
|
+
from rucio.common.types import InternalScope
|
|
39
|
+
from rucio.daemons.c3po.collectors.free_space import FreeSpaceCollector
|
|
40
|
+
from rucio.daemons.c3po.collectors.jedi_did import JediDIDCollector
|
|
41
|
+
from rucio.daemons.c3po.collectors.workload import WorkloadCollector
|
|
42
|
+
|
|
43
|
+
if TYPE_CHECKING:
|
|
44
|
+
from types import FrameType
|
|
45
|
+
|
|
46
|
+
GRACEFUL_STOP = Event()
|
|
47
|
+
DAEMON_NAME = 'c3po'
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def read_free_space(
|
|
51
|
+
once: bool = False,
|
|
52
|
+
thread: int = 0,
|
|
53
|
+
waiting_time: int = 1800,
|
|
54
|
+
sleep_time: int = 10
|
|
55
|
+
) -> None:
|
|
56
|
+
"""
|
|
57
|
+
Thread to collect the space usage information for RSEs.
|
|
58
|
+
"""
|
|
59
|
+
free_space_collector = FreeSpaceCollector()
|
|
60
|
+
timer = waiting_time
|
|
61
|
+
while not GRACEFUL_STOP.is_set():
|
|
62
|
+
if timer < waiting_time:
|
|
63
|
+
timer += sleep_time
|
|
64
|
+
sleep(sleep_time)
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
logging.info('collecting free space')
|
|
68
|
+
free_space_collector.collect_free_space()
|
|
69
|
+
timer = 0
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def read_workload(
|
|
73
|
+
once: bool = False,
|
|
74
|
+
thread: int = 0,
|
|
75
|
+
waiting_time: int = 1800,
|
|
76
|
+
sleep_time: int = 10
|
|
77
|
+
) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Thread to collect the workload information from PanDA.
|
|
80
|
+
"""
|
|
81
|
+
workload_collector = WorkloadCollector()
|
|
82
|
+
timer = waiting_time
|
|
83
|
+
while not GRACEFUL_STOP.is_set():
|
|
84
|
+
if timer < waiting_time:
|
|
85
|
+
timer += sleep_time
|
|
86
|
+
sleep(sleep_time)
|
|
87
|
+
continue
|
|
88
|
+
|
|
89
|
+
logging.info('collecting workload')
|
|
90
|
+
workload_collector.collect_workload()
|
|
91
|
+
timer = 0
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def print_workload(
|
|
95
|
+
once: bool = False,
|
|
96
|
+
thread: int = 0,
|
|
97
|
+
waiting_time: int = 600,
|
|
98
|
+
sleep_time: int = 10
|
|
99
|
+
) -> None:
|
|
100
|
+
"""
|
|
101
|
+
Thread to regularly output the workload to logs for debugging.
|
|
102
|
+
"""
|
|
103
|
+
workload_collector = WorkloadCollector()
|
|
104
|
+
timer = waiting_time
|
|
105
|
+
while not GRACEFUL_STOP.is_set():
|
|
106
|
+
if timer < waiting_time:
|
|
107
|
+
timer += sleep_time
|
|
108
|
+
sleep(sleep_time)
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
logging.info('Number of sites cached %d' % len(workload_collector.get_sites()))
|
|
112
|
+
for site in workload_collector.get_sites():
|
|
113
|
+
logging.info('%s: %d / %d / %d' % (site, workload_collector.get_cur_jobs(site), workload_collector.get_avg_jobs(site), workload_collector.get_max_jobs(site)))
|
|
114
|
+
timer = 0
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def read_dids(
|
|
118
|
+
once: bool = False,
|
|
119
|
+
thread: int = 0,
|
|
120
|
+
did_collector: Optional[JediDIDCollector] = None,
|
|
121
|
+
waiting_time: int = 60,
|
|
122
|
+
sleep_time: int = 10
|
|
123
|
+
) -> None:
|
|
124
|
+
"""
|
|
125
|
+
Thread to collect DIDs for the placement algorithm.
|
|
126
|
+
"""
|
|
127
|
+
timer = waiting_time
|
|
128
|
+
while not GRACEFUL_STOP.is_set():
|
|
129
|
+
if timer < waiting_time:
|
|
130
|
+
timer += sleep_time
|
|
131
|
+
sleep(sleep_time)
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
if did_collector is not None:
|
|
135
|
+
did_collector.get_dids()
|
|
136
|
+
timer = 0
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def add_rule(
|
|
140
|
+
client: Client,
|
|
141
|
+
did: dict[str, str],
|
|
142
|
+
src_rse: str,
|
|
143
|
+
dst_rse: str
|
|
144
|
+
) -> None:
|
|
145
|
+
logging.debug('add rule for %s from %s to %s' % (did, src_rse, dst_rse))
|
|
146
|
+
r = client.add_replication_rule([did, ], 1, dst_rse, lifetime=604800, account='c3po', source_replica_expression=src_rse, activity='Data Brokering', asynchronous=True)
|
|
147
|
+
logging.debug(r)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def place_replica(
|
|
151
|
+
did_queue: Queue,
|
|
152
|
+
once: bool = False,
|
|
153
|
+
thread: int = 0,
|
|
154
|
+
waiting_time: int = 100,
|
|
155
|
+
dry_run: bool = False,
|
|
156
|
+
sampling: bool = False,
|
|
157
|
+
algorithms: str = 't2_free_space_only_pop_with_network',
|
|
158
|
+
datatypes: str = 'NTUP,DAOD',
|
|
159
|
+
dest_rse_expr: str = 'type=DATADISK',
|
|
160
|
+
max_bytes_hour: int = 100000000000000,
|
|
161
|
+
max_files_hour: int = 100000,
|
|
162
|
+
max_bytes_hour_rse: int = 50000000000000,
|
|
163
|
+
max_files_hour_rse: int = 10000,
|
|
164
|
+
min_popularity: int = 8,
|
|
165
|
+
min_recent_requests: int = 5,
|
|
166
|
+
max_replicas: int = 5,
|
|
167
|
+
sleep_time: int = 10
|
|
168
|
+
) -> None:
|
|
169
|
+
"""
|
|
170
|
+
Thread to run the placement algorithm to decide if and where to put new replicas.
|
|
171
|
+
"""
|
|
172
|
+
try:
|
|
173
|
+
c3po_options = config_get_options('c3po')
|
|
174
|
+
client = None
|
|
175
|
+
|
|
176
|
+
if 'algorithms' in c3po_options:
|
|
177
|
+
algorithms = config_get('c3po', 'algorithms')
|
|
178
|
+
|
|
179
|
+
algorithms_list = algorithms.split(',')
|
|
180
|
+
|
|
181
|
+
if not dry_run:
|
|
182
|
+
if len(algorithms_list) != 1:
|
|
183
|
+
logging.error('Multiple algorithms are only allowed in dry_run mode')
|
|
184
|
+
return
|
|
185
|
+
client = Client(auth_type='x509_proxy', account='c3po', creds={'client_proxy': '/opt/rucio/etc/ddmadmin.long.proxy'})
|
|
186
|
+
|
|
187
|
+
vo = client.vo
|
|
188
|
+
instances = {}
|
|
189
|
+
for algorithm in algorithms_list:
|
|
190
|
+
module_path = 'rucio.daemons.c3po.algorithms.' + algorithm
|
|
191
|
+
module = __import__(module_path, globals(), locals(), ['PlacementAlgorithm'])
|
|
192
|
+
instance = module.PlacementAlgorithm(datatypes, dest_rse_expr, max_bytes_hour, max_files_hour, max_bytes_hour_rse, max_files_hour_rse, min_popularity, min_recent_requests, max_replicas)
|
|
193
|
+
instances[algorithm] = instance
|
|
194
|
+
|
|
195
|
+
params = {
|
|
196
|
+
'dry_run': dry_run,
|
|
197
|
+
'sampling': sampling,
|
|
198
|
+
'datatypes': datatypes,
|
|
199
|
+
'dest_rse_expr': dest_rse_expr,
|
|
200
|
+
'max_bytes_hour': max_bytes_hour,
|
|
201
|
+
'max_files_hour': max_files_hour,
|
|
202
|
+
'max_bytes_hour_rse': max_bytes_hour_rse,
|
|
203
|
+
'max_files_hour_rse': max_files_hour_rse,
|
|
204
|
+
'min_recent_requests': min_recent_requests,
|
|
205
|
+
'min_popularity': min_popularity
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
instance_id = str(uuid4()).split('-')[0]
|
|
209
|
+
|
|
210
|
+
elastic_url = config_get('c3po', 'elastic_url')
|
|
211
|
+
elastic_index = config_get('c3po', 'elastic_index')
|
|
212
|
+
|
|
213
|
+
ca_cert = False
|
|
214
|
+
if 'ca_cert' in c3po_options:
|
|
215
|
+
ca_cert = config_get('c3po', 'ca_cert')
|
|
216
|
+
|
|
217
|
+
auth = False
|
|
218
|
+
if ('elastic_user' in c3po_options) and ('elastic_pass' in c3po_options):
|
|
219
|
+
auth = HTTPBasicAuth(config_get('c3po', 'elastic_user'), config_get('c3po', 'elastic_pass'))
|
|
220
|
+
|
|
221
|
+
w = waiting_time
|
|
222
|
+
while not GRACEFUL_STOP.is_set():
|
|
223
|
+
if w < waiting_time:
|
|
224
|
+
w += sleep_time
|
|
225
|
+
sleep(sleep_time)
|
|
226
|
+
continue
|
|
227
|
+
len_dids = did_queue.qsize()
|
|
228
|
+
|
|
229
|
+
if len_dids > 0:
|
|
230
|
+
logging.debug('(%s) %d did(s) in queue' % (instance_id, len_dids))
|
|
231
|
+
else:
|
|
232
|
+
logging.debug('(%s) no dids in queue' % (instance_id))
|
|
233
|
+
|
|
234
|
+
for _ in range(0, len_dids):
|
|
235
|
+
did = did_queue.get()
|
|
236
|
+
if isinstance(did[0], str):
|
|
237
|
+
did[0] = InternalScope(did[0], vo=vo)
|
|
238
|
+
for algorithm, instance in instances.items():
|
|
239
|
+
logging.info('(%s:%s) Retrieved %s:%s from queue. Run placement algorithm' % (algorithm, instance_id, did[0], did[1]))
|
|
240
|
+
decision = instance.place(did)
|
|
241
|
+
decision['@timestamp'] = datetime.utcnow().isoformat()
|
|
242
|
+
decision['algorithm'] = algorithm
|
|
243
|
+
decision['instance_id'] = instance_id
|
|
244
|
+
decision['params'] = params
|
|
245
|
+
|
|
246
|
+
create_rule = True
|
|
247
|
+
if sampling and 'error_reason' not in decision:
|
|
248
|
+
create_rule = bool(ord(md5(decision['did']).hexdigest()[-1]) & 1)
|
|
249
|
+
decision['create_rule'] = create_rule
|
|
250
|
+
# write the output to ES for further analysis
|
|
251
|
+
index_url = elastic_url + '/' + elastic_index + '-' + datetime.utcnow().strftime('%Y-%m') + '/record/'
|
|
252
|
+
try:
|
|
253
|
+
if ca_cert:
|
|
254
|
+
r = post(index_url, data=dumps(decision), verify=ca_cert, auth=auth)
|
|
255
|
+
else:
|
|
256
|
+
r = post(index_url, data=dumps(decision))
|
|
257
|
+
if r.status_code != 201:
|
|
258
|
+
logging.error(r)
|
|
259
|
+
logging.error('(%s:%s) could not write to ElasticSearch' % (algorithm, instance_id))
|
|
260
|
+
except RequestException as e:
|
|
261
|
+
logging.error('(%s:%s) could not write to ElasticSearch' % (algorithm, instance_id))
|
|
262
|
+
logging.error(e)
|
|
263
|
+
continue
|
|
264
|
+
|
|
265
|
+
logging.debug(decision)
|
|
266
|
+
if 'error_reason' in decision:
|
|
267
|
+
logging.error('(%s:%s) The placement algorithm ran into an error: %s' % (algorithm, instance_id, decision['error_reason']))
|
|
268
|
+
continue
|
|
269
|
+
|
|
270
|
+
logging.info('(%s:%s) Decided to place a new replica for %s on %s' % (algorithm, instance_id, decision['did'], decision['destination_rse']))
|
|
271
|
+
|
|
272
|
+
if (not dry_run) and create_rule:
|
|
273
|
+
# DO IT!
|
|
274
|
+
try:
|
|
275
|
+
add_rule(client, {'scope': did[0].external, 'name': did[1]}, decision.get('source_rse'), decision.get('destination_rse')) # type: ignore
|
|
276
|
+
except exception.RucioException as e:
|
|
277
|
+
logging.debug(e)
|
|
278
|
+
|
|
279
|
+
w = 0
|
|
280
|
+
except Exception as e:
|
|
281
|
+
logging.critical(e)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def stop(signum: Optional[int] = None, frame: Optional['FrameType'] = None) -> None:
|
|
285
|
+
"""
|
|
286
|
+
Graceful exit.
|
|
287
|
+
"""
|
|
288
|
+
GRACEFUL_STOP.set()
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def run(
|
|
292
|
+
once: bool = False,
|
|
293
|
+
threads: int = 1,
|
|
294
|
+
only_workload: bool = False,
|
|
295
|
+
dry_run: bool = False,
|
|
296
|
+
sampling: bool = False,
|
|
297
|
+
algorithms: str = 't2_free_space_only_pop_with_network',
|
|
298
|
+
datatypes: str = 'NTUP,DAOD',
|
|
299
|
+
dest_rse_expr: str = 'type=DATADISK',
|
|
300
|
+
max_bytes_hour: int = 100000000000000,
|
|
301
|
+
max_files_hour: int = 100000,
|
|
302
|
+
max_bytes_hour_rse: int = 50000000000000,
|
|
303
|
+
max_files_hour_rse: int = 10000,
|
|
304
|
+
min_popularity: int = 8,
|
|
305
|
+
min_recent_requests: int = 5,
|
|
306
|
+
max_replicas: int = 5,
|
|
307
|
+
waiting_time_read_free_space: int = 1800,
|
|
308
|
+
waiting_time_read_workload: int = 1800,
|
|
309
|
+
waiting_time_print_workload: int = 600,
|
|
310
|
+
waiting_time_read_dids: int = 60,
|
|
311
|
+
waiting_time_place_replica: int = 100,
|
|
312
|
+
sleep_time: int = 10
|
|
313
|
+
) -> None:
|
|
314
|
+
"""
|
|
315
|
+
Starts up the main thread
|
|
316
|
+
"""
|
|
317
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
318
|
+
|
|
319
|
+
if rucio.db.sqla.util.is_old_db():
|
|
320
|
+
raise exception.DatabaseException('Database was not updated, daemon won\'t start')
|
|
321
|
+
|
|
322
|
+
logging.info('activating C-3PO')
|
|
323
|
+
|
|
324
|
+
thread_list = []
|
|
325
|
+
try:
|
|
326
|
+
if only_workload:
|
|
327
|
+
logging.info('running in workload-collector-only mode')
|
|
328
|
+
thread_list.append(Thread(target=read_workload, name='read_workload', kwargs={'thread': 0,
|
|
329
|
+
'waiting_time': waiting_time_read_workload,
|
|
330
|
+
'sleep_time': sleep_time}))
|
|
331
|
+
thread_list.append(Thread(target=print_workload, name='print_workload', kwargs={'thread': 0,
|
|
332
|
+
'waiting_time': waiting_time_print_workload,
|
|
333
|
+
'sleep_time': sleep_time}))
|
|
334
|
+
else:
|
|
335
|
+
logging.info('running in placement mode')
|
|
336
|
+
did_queue = Queue()
|
|
337
|
+
dc = JediDIDCollector(did_queue)
|
|
338
|
+
|
|
339
|
+
thread_list.append(Thread(target=read_free_space, name='read_free_space', kwargs={'thread': 0,
|
|
340
|
+
'waiting_time': waiting_time_read_free_space,
|
|
341
|
+
'sleep_time': sleep_time}))
|
|
342
|
+
thread_list.append(Thread(target=read_dids, name='read_dids', kwargs={'thread': 0,
|
|
343
|
+
'did_collector': dc,
|
|
344
|
+
'waiting_time': waiting_time_read_dids,
|
|
345
|
+
'sleep_time': sleep_time}))
|
|
346
|
+
thread_list.append(Thread(target=place_replica, name='place_replica', kwargs={'thread': 0,
|
|
347
|
+
'did_queue': did_queue,
|
|
348
|
+
'waiting_time': waiting_time_place_replica,
|
|
349
|
+
'algorithms': algorithms,
|
|
350
|
+
'dry_run': dry_run,
|
|
351
|
+
'sampling': sampling,
|
|
352
|
+
'datatypes': datatypes,
|
|
353
|
+
'dest_rse_expr': dest_rse_expr,
|
|
354
|
+
'max_bytes_hour': max_bytes_hour,
|
|
355
|
+
'max_files_hour': max_files_hour,
|
|
356
|
+
'max_bytes_hour_rse': max_bytes_hour_rse,
|
|
357
|
+
'max_files_hour_rse': max_files_hour_rse,
|
|
358
|
+
'min_popularity': min_popularity,
|
|
359
|
+
'min_recent_requests': min_recent_requests,
|
|
360
|
+
'max_replicas': max_replicas,
|
|
361
|
+
'sleep_time': sleep_time}))
|
|
362
|
+
|
|
363
|
+
for t in thread_list:
|
|
364
|
+
t.start()
|
|
365
|
+
|
|
366
|
+
logging.info('waiting for interrupts')
|
|
367
|
+
|
|
368
|
+
while len(thread_list) > 0:
|
|
369
|
+
[t.join(timeout=3) for t in thread_list if t and t.is_alive()]
|
|
370
|
+
except Exception as error:
|
|
371
|
+
logging.critical(error)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
@@ -0,0 +1,108 @@
|
|
|
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
|
+
from json import loads
|
|
16
|
+
from typing import Optional
|
|
17
|
+
|
|
18
|
+
from requests import get
|
|
19
|
+
|
|
20
|
+
from rucio.common.config import config_get
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class MappingCollector:
|
|
24
|
+
"""
|
|
25
|
+
Provides mappings from PanDA / DDM resources to ATLAS sites and back.
|
|
26
|
+
"""
|
|
27
|
+
class _MappingCollector:
|
|
28
|
+
'''
|
|
29
|
+
_MappingCollector
|
|
30
|
+
'''
|
|
31
|
+
|
|
32
|
+
def __init__(self):
|
|
33
|
+
'''
|
|
34
|
+
__init__
|
|
35
|
+
'''
|
|
36
|
+
self._fetch_panda_mapping()
|
|
37
|
+
self._fetch_ddm_mapping()
|
|
38
|
+
|
|
39
|
+
def _fetch_panda_mapping(self) -> None:
|
|
40
|
+
'''
|
|
41
|
+
_fetch_panda_mapping
|
|
42
|
+
'''
|
|
43
|
+
result = get(config_get('c3po-site-mapper', 'panda_url'))
|
|
44
|
+
data = loads(result.text)
|
|
45
|
+
self.panda_to_site = {}
|
|
46
|
+
self.site_to_panda = {}
|
|
47
|
+
|
|
48
|
+
for entry in data:
|
|
49
|
+
self.panda_to_site[entry['panda_resource']] = entry['atlas_site']
|
|
50
|
+
if entry['atlas_site'] not in self.site_to_panda:
|
|
51
|
+
self.site_to_panda[entry['atlas_site']] = []
|
|
52
|
+
self.site_to_panda[entry['atlas_site']].append(entry['panda_resource'])
|
|
53
|
+
|
|
54
|
+
def _fetch_ddm_mapping(self) -> None:
|
|
55
|
+
'''
|
|
56
|
+
_fetch_ddm_mapping
|
|
57
|
+
'''
|
|
58
|
+
result = get(config_get('c3po-site-mapper', 'ddm_url'))
|
|
59
|
+
data = loads(result.text)
|
|
60
|
+
self.site_to_ddm = {}
|
|
61
|
+
self.ddm_to_site = {}
|
|
62
|
+
|
|
63
|
+
for entry in data:
|
|
64
|
+
self.ddm_to_site[entry['name']] = entry['site']
|
|
65
|
+
if entry['site'] not in self.site_to_ddm:
|
|
66
|
+
self.site_to_ddm[entry['site']] = []
|
|
67
|
+
self.site_to_ddm[entry['site']].append(entry['name'])
|
|
68
|
+
|
|
69
|
+
instance = None
|
|
70
|
+
|
|
71
|
+
def __init__(self):
|
|
72
|
+
'''
|
|
73
|
+
__init__
|
|
74
|
+
'''
|
|
75
|
+
if not MappingCollector.instance:
|
|
76
|
+
MappingCollector.instance = MappingCollector._MappingCollector()
|
|
77
|
+
|
|
78
|
+
def ddm_to_site(self, ddm: str) -> Optional[str]:
|
|
79
|
+
'''
|
|
80
|
+
ddm_to_site
|
|
81
|
+
'''
|
|
82
|
+
if ddm not in self.instance.ddm_to_site: # type: ignore
|
|
83
|
+
return None
|
|
84
|
+
return self.instance.ddm_to_site[ddm] # type: ignore
|
|
85
|
+
|
|
86
|
+
def panda_to_site(self, panda: str) -> Optional[str]:
|
|
87
|
+
'''
|
|
88
|
+
panda_to_site
|
|
89
|
+
'''
|
|
90
|
+
if panda not in self.instance.panda_to_site: # type: ignore
|
|
91
|
+
return None
|
|
92
|
+
return self.instance.panda_to_site[panda] # type: ignore
|
|
93
|
+
|
|
94
|
+
def site_to_ddm(self, site: str) -> Optional[str]:
|
|
95
|
+
'''
|
|
96
|
+
site_to_ddm
|
|
97
|
+
'''
|
|
98
|
+
if site not in self.instance.site_to_ddm: # type: ignore
|
|
99
|
+
return None
|
|
100
|
+
return self.instance.site_to_ddm[site] # type: ignore
|
|
101
|
+
|
|
102
|
+
def site_to_panda(self, site: str) -> Optional[str]:
|
|
103
|
+
'''
|
|
104
|
+
site_to_panda
|
|
105
|
+
'''
|
|
106
|
+
if site not in self.instance.site_to_panda: # type: ignore
|
|
107
|
+
return None
|
|
108
|
+
return self.instance.site_to_panda[site] # type: ignore
|
|
@@ -0,0 +1,81 @@
|
|
|
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
|
+
Collector to get the SRM free and used information for DATADISK RSEs.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from typing import TYPE_CHECKING, Optional
|
|
20
|
+
|
|
21
|
+
from sqlalchemy import and_, select
|
|
22
|
+
|
|
23
|
+
from rucio.db.sqla.models import RSEAttrAssociation, RSEUsage
|
|
24
|
+
from rucio.db.sqla.session import read_session
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from sqlalchemy.orm import Session
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class FreeSpaceCollector:
|
|
31
|
+
"""
|
|
32
|
+
Collector to get the SRM free and used information for DATADISK RSEs.
|
|
33
|
+
"""
|
|
34
|
+
class _FreeSpaceCollector:
|
|
35
|
+
"""
|
|
36
|
+
Hidden implementation
|
|
37
|
+
"""
|
|
38
|
+
def __init__(self):
|
|
39
|
+
self.rses = {}
|
|
40
|
+
|
|
41
|
+
@read_session
|
|
42
|
+
def _collect_free_space(
|
|
43
|
+
self,
|
|
44
|
+
*,
|
|
45
|
+
session: Optional["Session"] = None
|
|
46
|
+
) -> None:
|
|
47
|
+
"""
|
|
48
|
+
Retrieve free space from database
|
|
49
|
+
"""
|
|
50
|
+
stmt = select(
|
|
51
|
+
RSEUsage.rse_id,
|
|
52
|
+
RSEUsage.free,
|
|
53
|
+
RSEUsage.used
|
|
54
|
+
).join(
|
|
55
|
+
RSEAttrAssociation,
|
|
56
|
+
RSEAttrAssociation.rse_id == RSEUsage.rse_id
|
|
57
|
+
).where(
|
|
58
|
+
and_(RSEUsage.source == 'storage',
|
|
59
|
+
RSEAttrAssociation.key == 'type',
|
|
60
|
+
RSEAttrAssociation.value == 'DATADISK'),
|
|
61
|
+
)
|
|
62
|
+
for rse_id, free, used in session.execute(stmt).all(): # type: ignore (session could be None)
|
|
63
|
+
self.rses[rse_id] = {'total': used + free, 'used': used, 'free': free}
|
|
64
|
+
|
|
65
|
+
instance = None
|
|
66
|
+
|
|
67
|
+
def __init__(self):
|
|
68
|
+
if not FreeSpaceCollector.instance:
|
|
69
|
+
FreeSpaceCollector.instance = FreeSpaceCollector._FreeSpaceCollector()
|
|
70
|
+
|
|
71
|
+
def collect_free_space(self) -> None:
|
|
72
|
+
"""
|
|
73
|
+
Execute the free space collector
|
|
74
|
+
"""
|
|
75
|
+
self.instance._collect_free_space() # type: ignore
|
|
76
|
+
|
|
77
|
+
def get_rse_space(self) -> dict[str, dict[str, int]]:
|
|
78
|
+
"""
|
|
79
|
+
Return the RSE space
|
|
80
|
+
"""
|
|
81
|
+
return self.instance.rses # type: ignore
|
|
@@ -0,0 +1,57 @@
|
|
|
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 logging
|
|
16
|
+
from typing import TYPE_CHECKING, Optional
|
|
17
|
+
|
|
18
|
+
from rucio.db.sqla.session import read_session
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from queue import Queue
|
|
22
|
+
|
|
23
|
+
from sqlalchemy.orm import Session
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class JediDIDCollector:
|
|
27
|
+
def __init__(self, queue: "Queue"):
|
|
28
|
+
self.queue = queue
|
|
29
|
+
self.max_tid = 0
|
|
30
|
+
|
|
31
|
+
@read_session
|
|
32
|
+
def get_dids(
|
|
33
|
+
self,
|
|
34
|
+
*,
|
|
35
|
+
session: Optional["Session"] = None
|
|
36
|
+
) -> None:
|
|
37
|
+
query = """select t.jeditaskid, t.username, t.status, d.datasetname from ATLAS_PANDA.JEDI_TASKS t
|
|
38
|
+
inner join ATLAS_PANDA.JEDI_DATASETS d
|
|
39
|
+
on t.jeditaskid = d.jeditaskid
|
|
40
|
+
where t.creationdate > SYS_EXTRACT_UTC(systimestamp) - 5/(24*60) and t.tasktype = 'anal' and t.prodsourcelabel = 'user'
|
|
41
|
+
and d.type = 'input'
|
|
42
|
+
order by d.jeditaskid asc"""
|
|
43
|
+
|
|
44
|
+
tasks = session.execute(query) # type: ignore
|
|
45
|
+
|
|
46
|
+
for t in tasks.fetchall():
|
|
47
|
+
status = t[2]
|
|
48
|
+
if status == 'running':
|
|
49
|
+
continue
|
|
50
|
+
tid = t[0]
|
|
51
|
+
if tid < self.max_tid:
|
|
52
|
+
continue
|
|
53
|
+
|
|
54
|
+
logging.debug("Received task: " + str(t))
|
|
55
|
+
did = t[3].split(':')
|
|
56
|
+
self.queue.put((did[0], did[1]))
|
|
57
|
+
self.max_tid = tid
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
Mock DID collector
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from secrets import choice
|
|
20
|
+
from typing import TYPE_CHECKING
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from multiprocessing import Queue
|
|
24
|
+
|
|
25
|
+
from _typeshed import FileDescriptorOrPath
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class MockDIDCollector:
|
|
29
|
+
"""
|
|
30
|
+
Simple collector that reads dids from a file. Used to
|
|
31
|
+
test the interface.
|
|
32
|
+
"""
|
|
33
|
+
def __init__(self, queue: "Queue"):
|
|
34
|
+
self._queue = queue
|
|
35
|
+
self._read_file('/opt/rucio/etc/dids_mc15_13TeV.csv')
|
|
36
|
+
|
|
37
|
+
def _read_file(self, infile: "FileDescriptorOrPath") -> None:
|
|
38
|
+
dids = []
|
|
39
|
+
with open(infile, 'r') as f:
|
|
40
|
+
f.readline()
|
|
41
|
+
for line in f:
|
|
42
|
+
items = line.strip().split('\t')
|
|
43
|
+
scope = items[0]
|
|
44
|
+
name = items[1]
|
|
45
|
+
dids.append((scope, name))
|
|
46
|
+
|
|
47
|
+
self._dids = tuple(dids)
|
|
48
|
+
|
|
49
|
+
def get_dids(self) -> None:
|
|
50
|
+
did = choice(self._dids)
|
|
51
|
+
self._queue.put(did)
|