rucio 32.8.6__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 +18 -0
- rucio/alembicrevision.py +16 -0
- rucio/api/__init__.py +14 -0
- rucio/api/account.py +266 -0
- rucio/api/account_limit.py +287 -0
- rucio/api/authentication.py +302 -0
- rucio/api/config.py +218 -0
- rucio/api/credential.py +60 -0
- rucio/api/did.py +726 -0
- rucio/api/dirac.py +71 -0
- rucio/api/exporter.py +60 -0
- rucio/api/heartbeat.py +62 -0
- rucio/api/identity.py +160 -0
- rucio/api/importer.py +46 -0
- rucio/api/lifetime_exception.py +95 -0
- rucio/api/lock.py +131 -0
- rucio/api/meta.py +85 -0
- rucio/api/permission.py +72 -0
- rucio/api/quarantined_replica.py +69 -0
- rucio/api/replica.py +528 -0
- rucio/api/request.py +220 -0
- rucio/api/rse.py +601 -0
- rucio/api/rule.py +335 -0
- rucio/api/scope.py +89 -0
- rucio/api/subscription.py +255 -0
- rucio/api/temporary_did.py +49 -0
- rucio/api/vo.py +112 -0
- rucio/client/__init__.py +16 -0
- rucio/client/accountclient.py +413 -0
- rucio/client/accountlimitclient.py +155 -0
- rucio/client/baseclient.py +929 -0
- rucio/client/client.py +77 -0
- rucio/client/configclient.py +113 -0
- rucio/client/credentialclient.py +54 -0
- rucio/client/didclient.py +691 -0
- rucio/client/diracclient.py +48 -0
- rucio/client/downloadclient.py +1674 -0
- rucio/client/exportclient.py +44 -0
- rucio/client/fileclient.py +51 -0
- rucio/client/importclient.py +42 -0
- rucio/client/lifetimeclient.py +74 -0
- rucio/client/lockclient.py +99 -0
- rucio/client/metaclient.py +137 -0
- rucio/client/pingclient.py +45 -0
- rucio/client/replicaclient.py +444 -0
- rucio/client/requestclient.py +109 -0
- rucio/client/rseclient.py +664 -0
- rucio/client/ruleclient.py +287 -0
- rucio/client/scopeclient.py +88 -0
- rucio/client/subscriptionclient.py +161 -0
- rucio/client/touchclient.py +78 -0
- rucio/client/uploadclient.py +871 -0
- rucio/common/__init__.py +14 -0
- rucio/common/cache.py +74 -0
- rucio/common/config.py +796 -0
- rucio/common/constants.py +92 -0
- rucio/common/constraints.py +18 -0
- rucio/common/didtype.py +187 -0
- rucio/common/dumper/__init__.py +306 -0
- rucio/common/dumper/consistency.py +449 -0
- rucio/common/dumper/data_models.py +325 -0
- rucio/common/dumper/path_parsing.py +65 -0
- rucio/common/exception.py +1092 -0
- rucio/common/extra.py +37 -0
- rucio/common/logging.py +404 -0
- rucio/common/pcache.py +1387 -0
- rucio/common/policy.py +84 -0
- rucio/common/schema/__init__.py +143 -0
- rucio/common/schema/atlas.py +411 -0
- rucio/common/schema/belleii.py +406 -0
- rucio/common/schema/cms.py +478 -0
- rucio/common/schema/domatpc.py +399 -0
- rucio/common/schema/escape.py +424 -0
- rucio/common/schema/generic.py +431 -0
- rucio/common/schema/generic_multi_vo.py +410 -0
- rucio/common/schema/icecube.py +404 -0
- rucio/common/schema/lsst.py +423 -0
- rucio/common/stomp_utils.py +160 -0
- rucio/common/stopwatch.py +56 -0
- rucio/common/test_rucio_server.py +148 -0
- rucio/common/types.py +158 -0
- rucio/common/utils.py +1946 -0
- rucio/core/__init__.py +14 -0
- rucio/core/account.py +426 -0
- rucio/core/account_counter.py +171 -0
- rucio/core/account_limit.py +357 -0
- rucio/core/authentication.py +563 -0
- rucio/core/config.py +386 -0
- rucio/core/credential.py +218 -0
- rucio/core/did.py +3102 -0
- rucio/core/did_meta_plugins/__init__.py +250 -0
- rucio/core/did_meta_plugins/did_column_meta.py +326 -0
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +116 -0
- rucio/core/did_meta_plugins/filter_engine.py +573 -0
- rucio/core/did_meta_plugins/json_meta.py +215 -0
- rucio/core/did_meta_plugins/mongo_meta.py +199 -0
- rucio/core/did_meta_plugins/postgres_meta.py +317 -0
- rucio/core/dirac.py +208 -0
- rucio/core/distance.py +164 -0
- rucio/core/exporter.py +59 -0
- rucio/core/heartbeat.py +263 -0
- rucio/core/identity.py +290 -0
- rucio/core/importer.py +248 -0
- rucio/core/lifetime_exception.py +377 -0
- rucio/core/lock.py +474 -0
- rucio/core/message.py +241 -0
- rucio/core/meta.py +190 -0
- rucio/core/monitor.py +441 -0
- rucio/core/naming_convention.py +154 -0
- rucio/core/nongrid_trace.py +124 -0
- rucio/core/oidc.py +1339 -0
- rucio/core/permission/__init__.py +107 -0
- rucio/core/permission/atlas.py +1333 -0
- rucio/core/permission/belleii.py +1076 -0
- rucio/core/permission/cms.py +1166 -0
- rucio/core/permission/escape.py +1076 -0
- rucio/core/permission/generic.py +1128 -0
- rucio/core/permission/generic_multi_vo.py +1148 -0
- rucio/core/quarantined_replica.py +190 -0
- rucio/core/replica.py +3627 -0
- rucio/core/replica_sorter.py +368 -0
- rucio/core/request.py +2241 -0
- rucio/core/rse.py +1835 -0
- rucio/core/rse_counter.py +155 -0
- rucio/core/rse_expression_parser.py +460 -0
- rucio/core/rse_selector.py +277 -0
- rucio/core/rule.py +3419 -0
- rucio/core/rule_grouping.py +1473 -0
- rucio/core/scope.py +152 -0
- rucio/core/subscription.py +316 -0
- rucio/core/temporary_did.py +188 -0
- rucio/core/topology.py +448 -0
- rucio/core/trace.py +361 -0
- rucio/core/transfer.py +1233 -0
- rucio/core/vo.py +151 -0
- rucio/core/volatile_replica.py +123 -0
- rucio/daemons/__init__.py +14 -0
- rucio/daemons/abacus/__init__.py +14 -0
- rucio/daemons/abacus/account.py +106 -0
- rucio/daemons/abacus/collection_replica.py +113 -0
- rucio/daemons/abacus/rse.py +107 -0
- rucio/daemons/atropos/__init__.py +14 -0
- rucio/daemons/atropos/atropos.py +243 -0
- rucio/daemons/auditor/__init__.py +261 -0
- rucio/daemons/auditor/hdfs.py +86 -0
- rucio/daemons/auditor/srmdumps.py +284 -0
- rucio/daemons/automatix/__init__.py +14 -0
- rucio/daemons/automatix/automatix.py +281 -0
- rucio/daemons/badreplicas/__init__.py +14 -0
- rucio/daemons/badreplicas/minos.py +311 -0
- rucio/daemons/badreplicas/minos_temporary_expiration.py +173 -0
- rucio/daemons/badreplicas/necromancer.py +200 -0
- rucio/daemons/bb8/__init__.py +14 -0
- rucio/daemons/bb8/bb8.py +356 -0
- rucio/daemons/bb8/common.py +762 -0
- rucio/daemons/bb8/nuclei_background_rebalance.py +147 -0
- rucio/daemons/bb8/t2_background_rebalance.py +146 -0
- rucio/daemons/c3po/__init__.py +14 -0
- rucio/daemons/c3po/algorithms/__init__.py +14 -0
- rucio/daemons/c3po/algorithms/simple.py +131 -0
- rucio/daemons/c3po/algorithms/t2_free_space.py +125 -0
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +127 -0
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +279 -0
- rucio/daemons/c3po/c3po.py +342 -0
- rucio/daemons/c3po/collectors/__init__.py +14 -0
- rucio/daemons/c3po/collectors/agis.py +108 -0
- rucio/daemons/c3po/collectors/free_space.py +62 -0
- rucio/daemons/c3po/collectors/jedi_did.py +48 -0
- rucio/daemons/c3po/collectors/mock_did.py +46 -0
- rucio/daemons/c3po/collectors/network_metrics.py +63 -0
- rucio/daemons/c3po/collectors/workload.py +110 -0
- rucio/daemons/c3po/utils/__init__.py +14 -0
- rucio/daemons/c3po/utils/dataset_cache.py +40 -0
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +45 -0
- rucio/daemons/c3po/utils/expiring_list.py +63 -0
- rucio/daemons/c3po/utils/popularity.py +82 -0
- rucio/daemons/c3po/utils/timeseries.py +76 -0
- rucio/daemons/cache/__init__.py +14 -0
- rucio/daemons/cache/consumer.py +191 -0
- rucio/daemons/common.py +391 -0
- rucio/daemons/conveyor/__init__.py +14 -0
- rucio/daemons/conveyor/common.py +530 -0
- rucio/daemons/conveyor/finisher.py +492 -0
- rucio/daemons/conveyor/poller.py +372 -0
- rucio/daemons/conveyor/preparer.py +198 -0
- rucio/daemons/conveyor/receiver.py +206 -0
- rucio/daemons/conveyor/stager.py +127 -0
- rucio/daemons/conveyor/submitter.py +379 -0
- rucio/daemons/conveyor/throttler.py +468 -0
- rucio/daemons/follower/__init__.py +14 -0
- rucio/daemons/follower/follower.py +97 -0
- rucio/daemons/hermes/__init__.py +14 -0
- rucio/daemons/hermes/hermes.py +738 -0
- rucio/daemons/judge/__init__.py +14 -0
- rucio/daemons/judge/cleaner.py +149 -0
- rucio/daemons/judge/evaluator.py +172 -0
- rucio/daemons/judge/injector.py +154 -0
- rucio/daemons/judge/repairer.py +144 -0
- rucio/daemons/oauthmanager/__init__.py +14 -0
- rucio/daemons/oauthmanager/oauthmanager.py +199 -0
- rucio/daemons/reaper/__init__.py +14 -0
- rucio/daemons/reaper/dark_reaper.py +272 -0
- rucio/daemons/reaper/light_reaper.py +255 -0
- rucio/daemons/reaper/reaper.py +701 -0
- rucio/daemons/replicarecoverer/__init__.py +14 -0
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +487 -0
- rucio/daemons/storage/__init__.py +14 -0
- rucio/daemons/storage/consistency/__init__.py +14 -0
- rucio/daemons/storage/consistency/actions.py +753 -0
- rucio/daemons/tracer/__init__.py +14 -0
- rucio/daemons/tracer/kronos.py +513 -0
- rucio/daemons/transmogrifier/__init__.py +14 -0
- rucio/daemons/transmogrifier/transmogrifier.py +753 -0
- rucio/daemons/undertaker/__init__.py +14 -0
- rucio/daemons/undertaker/undertaker.py +137 -0
- rucio/db/__init__.py +14 -0
- rucio/db/sqla/__init__.py +38 -0
- rucio/db/sqla/constants.py +192 -0
- rucio/db/sqla/migrate_repo/__init__.py +14 -0
- rucio/db/sqla/migrate_repo/env.py +111 -0
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +71 -0
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +50 -0
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +61 -0
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +46 -0
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +93 -0
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +78 -0
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +46 -0
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +53 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +69 -0
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +42 -0
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +46 -0
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +61 -0
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +42 -0
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +141 -0
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +75 -0
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +75 -0
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +46 -0
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +51 -0
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +135 -0
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +65 -0
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +42 -0
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +66 -0
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +54 -0
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +46 -0
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +54 -0
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +39 -0
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +48 -0
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +48 -0
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +72 -0
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +46 -0
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +48 -0
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +48 -0
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +42 -0
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +69 -0
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +46 -0
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +78 -0
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +62 -0
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +74 -0
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +44 -0
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +67 -0
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +134 -0
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +58 -0
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +79 -0
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +61 -0
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +45 -0
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +46 -0
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +65 -0
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +42 -0
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +46 -0
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +46 -0
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +80 -0
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +61 -0
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +47 -0
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +46 -0
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +52 -0
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +42 -0
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +65 -0
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +46 -0
- rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +47 -0
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +45 -0
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +46 -0
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +48 -0
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +50 -0
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +48 -0
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +108 -0
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +57 -0
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +51 -0
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +50 -0
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +46 -0
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +42 -0
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +93 -0
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +73 -0
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +52 -0
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +45 -0
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +46 -0
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +54 -0
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +48 -0
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +70 -0
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +48 -0
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +95 -0
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +74 -0
- rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +78 -0
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +49 -0
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +124 -0
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +60 -0
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +53 -0
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +56 -0
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +67 -0
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +50 -0
- rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +46 -0
- rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +92 -0
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +42 -0
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +46 -0
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +147 -0
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +78 -0
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +53 -0
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +74 -0
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +56 -0
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +46 -0
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +68 -0
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +48 -0
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +149 -0
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +106 -0
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +45 -0
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +105 -0
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +52 -0
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +106 -0
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +30 -0
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +75 -0
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +49 -0
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +45 -0
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +38 -0
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +44 -0
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +46 -0
- rucio/db/sqla/models.py +1834 -0
- rucio/db/sqla/sautils.py +48 -0
- rucio/db/sqla/session.py +470 -0
- rucio/db/sqla/types.py +207 -0
- rucio/db/sqla/util.py +521 -0
- rucio/rse/__init__.py +97 -0
- rucio/rse/protocols/__init__.py +14 -0
- rucio/rse/protocols/cache.py +123 -0
- rucio/rse/protocols/dummy.py +112 -0
- rucio/rse/protocols/gfal.py +701 -0
- rucio/rse/protocols/globus.py +243 -0
- rucio/rse/protocols/gsiftp.py +93 -0
- rucio/rse/protocols/http_cache.py +83 -0
- rucio/rse/protocols/mock.py +124 -0
- rucio/rse/protocols/ngarc.py +210 -0
- rucio/rse/protocols/posix.py +251 -0
- rucio/rse/protocols/protocol.py +530 -0
- rucio/rse/protocols/rclone.py +365 -0
- rucio/rse/protocols/rfio.py +137 -0
- rucio/rse/protocols/srm.py +339 -0
- rucio/rse/protocols/ssh.py +414 -0
- rucio/rse/protocols/storm.py +207 -0
- rucio/rse/protocols/webdav.py +547 -0
- rucio/rse/protocols/xrootd.py +295 -0
- rucio/rse/rsemanager.py +752 -0
- rucio/tests/__init__.py +14 -0
- rucio/tests/common.py +244 -0
- rucio/tests/common_server.py +132 -0
- rucio/transfertool/__init__.py +14 -0
- rucio/transfertool/fts3.py +1484 -0
- rucio/transfertool/globus.py +200 -0
- rucio/transfertool/globus_library.py +182 -0
- rucio/transfertool/mock.py +81 -0
- rucio/transfertool/transfertool.py +212 -0
- rucio/vcsversion.py +11 -0
- rucio/version.py +46 -0
- rucio/web/__init__.py +14 -0
- rucio/web/rest/__init__.py +14 -0
- rucio/web/rest/flaskapi/__init__.py +14 -0
- rucio/web/rest/flaskapi/authenticated_bp.py +28 -0
- rucio/web/rest/flaskapi/v1/__init__.py +14 -0
- rucio/web/rest/flaskapi/v1/accountlimits.py +234 -0
- rucio/web/rest/flaskapi/v1/accounts.py +1088 -0
- rucio/web/rest/flaskapi/v1/archives.py +100 -0
- rucio/web/rest/flaskapi/v1/auth.py +1642 -0
- rucio/web/rest/flaskapi/v1/common.py +385 -0
- rucio/web/rest/flaskapi/v1/config.py +305 -0
- rucio/web/rest/flaskapi/v1/credentials.py +213 -0
- rucio/web/rest/flaskapi/v1/dids.py +2204 -0
- rucio/web/rest/flaskapi/v1/dirac.py +116 -0
- rucio/web/rest/flaskapi/v1/export.py +77 -0
- rucio/web/rest/flaskapi/v1/heartbeats.py +129 -0
- rucio/web/rest/flaskapi/v1/identities.py +263 -0
- rucio/web/rest/flaskapi/v1/import.py +133 -0
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +315 -0
- rucio/web/rest/flaskapi/v1/locks.py +360 -0
- rucio/web/rest/flaskapi/v1/main.py +83 -0
- rucio/web/rest/flaskapi/v1/meta.py +226 -0
- rucio/web/rest/flaskapi/v1/metrics.py +37 -0
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
- rucio/web/rest/flaskapi/v1/ping.py +89 -0
- rucio/web/rest/flaskapi/v1/redirect.py +366 -0
- rucio/web/rest/flaskapi/v1/replicas.py +1866 -0
- rucio/web/rest/flaskapi/v1/requests.py +841 -0
- rucio/web/rest/flaskapi/v1/rses.py +2204 -0
- rucio/web/rest/flaskapi/v1/rules.py +824 -0
- rucio/web/rest/flaskapi/v1/scopes.py +161 -0
- rucio/web/rest/flaskapi/v1/subscriptions.py +646 -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/tmp_dids.py +115 -0
- rucio/web/rest/flaskapi/v1/traces.py +100 -0
- rucio/web/rest/flaskapi/v1/vos.py +280 -0
- rucio/web/rest/main.py +19 -0
- rucio/web/rest/metrics.py +28 -0
- rucio-32.8.6.data/data/rucio/etc/alembic.ini.template +71 -0
- rucio-32.8.6.data/data/rucio/etc/alembic_offline.ini.template +74 -0
- rucio-32.8.6.data/data/rucio/etc/globus-config.yml.template +5 -0
- rucio-32.8.6.data/data/rucio/etc/ldap.cfg.template +30 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
- rucio-32.8.6.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
- rucio-32.8.6.data/data/rucio/etc/rucio.cfg.atlas.client.template +42 -0
- rucio-32.8.6.data/data/rucio/etc/rucio.cfg.template +257 -0
- rucio-32.8.6.data/data/rucio/etc/rucio_multi_vo.cfg.template +234 -0
- rucio-32.8.6.data/data/rucio/requirements.txt +55 -0
- rucio-32.8.6.data/data/rucio/tools/bootstrap.py +34 -0
- rucio-32.8.6.data/data/rucio/tools/merge_rucio_configs.py +147 -0
- rucio-32.8.6.data/data/rucio/tools/reset_database.py +40 -0
- rucio-32.8.6.data/scripts/rucio +2540 -0
- rucio-32.8.6.data/scripts/rucio-abacus-account +75 -0
- rucio-32.8.6.data/scripts/rucio-abacus-collection-replica +47 -0
- rucio-32.8.6.data/scripts/rucio-abacus-rse +79 -0
- rucio-32.8.6.data/scripts/rucio-admin +2434 -0
- rucio-32.8.6.data/scripts/rucio-atropos +61 -0
- rucio-32.8.6.data/scripts/rucio-auditor +199 -0
- rucio-32.8.6.data/scripts/rucio-automatix +51 -0
- rucio-32.8.6.data/scripts/rucio-bb8 +58 -0
- rucio-32.8.6.data/scripts/rucio-c3po +86 -0
- rucio-32.8.6.data/scripts/rucio-cache-client +135 -0
- rucio-32.8.6.data/scripts/rucio-cache-consumer +43 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-finisher +59 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-poller +67 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-preparer +38 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-receiver +44 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-stager +77 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-submitter +140 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-throttler +105 -0
- rucio-32.8.6.data/scripts/rucio-dark-reaper +54 -0
- rucio-32.8.6.data/scripts/rucio-dumper +159 -0
- rucio-32.8.6.data/scripts/rucio-follower +45 -0
- rucio-32.8.6.data/scripts/rucio-hermes +55 -0
- rucio-32.8.6.data/scripts/rucio-judge-cleaner +90 -0
- rucio-32.8.6.data/scripts/rucio-judge-evaluator +138 -0
- rucio-32.8.6.data/scripts/rucio-judge-injector +45 -0
- rucio-32.8.6.data/scripts/rucio-judge-repairer +45 -0
- rucio-32.8.6.data/scripts/rucio-kronos +45 -0
- rucio-32.8.6.data/scripts/rucio-light-reaper +53 -0
- rucio-32.8.6.data/scripts/rucio-minos +54 -0
- rucio-32.8.6.data/scripts/rucio-minos-temporary-expiration +51 -0
- rucio-32.8.6.data/scripts/rucio-necromancer +121 -0
- rucio-32.8.6.data/scripts/rucio-oauth-manager +64 -0
- rucio-32.8.6.data/scripts/rucio-reaper +84 -0
- rucio-32.8.6.data/scripts/rucio-replica-recoverer +249 -0
- rucio-32.8.6.data/scripts/rucio-storage-consistency-actions +75 -0
- rucio-32.8.6.data/scripts/rucio-transmogrifier +78 -0
- rucio-32.8.6.data/scripts/rucio-undertaker +77 -0
- rucio-32.8.6.dist-info/METADATA +83 -0
- rucio-32.8.6.dist-info/RECORD +481 -0
- rucio-32.8.6.dist-info/WHEEL +5 -0
- rucio-32.8.6.dist-info/licenses/AUTHORS.rst +94 -0
- rucio-32.8.6.dist-info/licenses/LICENSE +201 -0
- rucio-32.8.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
C3PO PanDA workload collector
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import logging
|
|
21
|
+
from json import loads
|
|
22
|
+
from time import time
|
|
23
|
+
|
|
24
|
+
from requests import get
|
|
25
|
+
|
|
26
|
+
from rucio.common.config import config_get, config_get_int
|
|
27
|
+
from rucio.daemons.c3po.utils.timeseries import RedisTimeSeries
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class WorkloadCollector(object):
|
|
31
|
+
"""
|
|
32
|
+
Collector to retrieve the workload from PanDA. It stores it as a time series in Redis and provides
|
|
33
|
+
the average and maximum number of running jobs for a sliding window.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
class __WorkloadCollector(object):
|
|
37
|
+
"""
|
|
38
|
+
Private class needed implement singleton.
|
|
39
|
+
"""
|
|
40
|
+
def __init__(self, delete_keys=False):
|
|
41
|
+
self._avg_jobs = {}
|
|
42
|
+
self._cur_jobs = {}
|
|
43
|
+
self._max_jobs = {}
|
|
44
|
+
self._tms = RedisTimeSeries(config_get('c3po', 'redis_host'), config_get_int('c3po', 'redis_port'), config_get_int('c3po-workload', 'window'), 'jobs_')
|
|
45
|
+
|
|
46
|
+
self._request_headers = {"Accept": "application/json", "Content-Type": "application/json"}
|
|
47
|
+
self._request_url = config_get('c3po-workload', 'panda_url')
|
|
48
|
+
if delete_keys:
|
|
49
|
+
self._tms.delete_keys()
|
|
50
|
+
self.reload_cache()
|
|
51
|
+
|
|
52
|
+
def reload_cache(self):
|
|
53
|
+
self._tms.trim()
|
|
54
|
+
|
|
55
|
+
for key in self._tms.get_keys():
|
|
56
|
+
site = "_".join(key.split('_')[1:])
|
|
57
|
+
job_series = self._tms.get_series(site)
|
|
58
|
+
num_jobs = len(job_series)
|
|
59
|
+
if num_jobs > 0:
|
|
60
|
+
self._avg_jobs[site] = sum(job_series) / num_jobs
|
|
61
|
+
self._max_jobs[site] = max(job_series)
|
|
62
|
+
self._cur_jobs[site] = job_series[-1]
|
|
63
|
+
|
|
64
|
+
def collect_workload(self):
|
|
65
|
+
start = time()
|
|
66
|
+
resp = get(self._request_url, headers=self._request_headers)
|
|
67
|
+
logging.debug("PanDA response took %fs" % (time() - start))
|
|
68
|
+
|
|
69
|
+
start = time()
|
|
70
|
+
jobs = loads(resp.text)['jobs']
|
|
71
|
+
logging.debug("decoding JSON response took %fs" % (time() - start))
|
|
72
|
+
sites = {}
|
|
73
|
+
|
|
74
|
+
start = time()
|
|
75
|
+
for job in jobs:
|
|
76
|
+
if job['computingsite'] not in sites:
|
|
77
|
+
sites[job['computingsite']] = 0
|
|
78
|
+
sites[job['computingsite']] += 1
|
|
79
|
+
for site, jobs in sites.items():
|
|
80
|
+
self._tms.add_point(site, jobs)
|
|
81
|
+
|
|
82
|
+
logging.debug("processing took %fs" % (time() - start))
|
|
83
|
+
self.reload_cache()
|
|
84
|
+
|
|
85
|
+
instance = None
|
|
86
|
+
|
|
87
|
+
def __init__(self):
|
|
88
|
+
if not WorkloadCollector.instance:
|
|
89
|
+
WorkloadCollector.instance = WorkloadCollector.__WorkloadCollector()
|
|
90
|
+
|
|
91
|
+
def get_avg_jobs(self, site):
|
|
92
|
+
return self.instance._avg_jobs[site]
|
|
93
|
+
|
|
94
|
+
def get_max_jobs(self, site):
|
|
95
|
+
return self.instance._max_jobs[site]
|
|
96
|
+
|
|
97
|
+
def get_cur_jobs(self, site):
|
|
98
|
+
return self.instance._cur_jobs[site]
|
|
99
|
+
|
|
100
|
+
def get_sites(self):
|
|
101
|
+
return list(self.instance._avg_jobs.keys())
|
|
102
|
+
|
|
103
|
+
def get_job_info(self, site):
|
|
104
|
+
return (self.get_cur_jobs(site), self.get_avg_jobs(site), self.get_max_jobs(site))
|
|
105
|
+
|
|
106
|
+
def get_series(self, site):
|
|
107
|
+
return self.instance._tms.get_series(site)
|
|
108
|
+
|
|
109
|
+
def collect_workload(self):
|
|
110
|
+
self.instance.collect_workload()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from uuid import uuid4
|
|
17
|
+
|
|
18
|
+
from rucio.daemons.c3po.utils.timeseries import RedisTimeSeries
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DatasetCache(object):
|
|
22
|
+
"""
|
|
23
|
+
Utility to count the accesses of the datasets during the last day.
|
|
24
|
+
"""
|
|
25
|
+
def __init__(self, redis_host, redis_port, timeout=1, prefix='did_cache', delete_keys=False):
|
|
26
|
+
self._prefix = prefix + '_' + str(uuid4()).split('-')[0]
|
|
27
|
+
self._tms = RedisTimeSeries(redis_host, redis_port, timeout, self._prefix)
|
|
28
|
+
|
|
29
|
+
if delete_keys:
|
|
30
|
+
self._tms.delete_keys()
|
|
31
|
+
|
|
32
|
+
def add_did(self, did):
|
|
33
|
+
self._tms.add_point('{}_{}'.format(did[0].internal, did[1]), 1)
|
|
34
|
+
|
|
35
|
+
def get_did(self, did):
|
|
36
|
+
self._tms.trim()
|
|
37
|
+
|
|
38
|
+
series = self._tms.get_series('{}_{}'.format(did[0].internal, did[1]))
|
|
39
|
+
|
|
40
|
+
return len(series)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
Expiring Dataset Cache
|
|
18
|
+
"""
|
|
19
|
+
from uuid import uuid4
|
|
20
|
+
|
|
21
|
+
from redis import StrictRedis
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ExpiringDatasetCache(object):
|
|
25
|
+
"""
|
|
26
|
+
Cache with expiring values to keep track of recently created replicas.
|
|
27
|
+
"""
|
|
28
|
+
def __init__(self, redis_host, redis_port, timeout=1, prefix='expiring_did_cache'):
|
|
29
|
+
self._redis = StrictRedis(host=redis_host, port=redis_port)
|
|
30
|
+
self._prefix = prefix + '_' + str(uuid4()).split('-')[0]
|
|
31
|
+
self._timeout = timeout
|
|
32
|
+
|
|
33
|
+
def add_dataset(self, dataset):
|
|
34
|
+
""" Adds a datasets to cache with lifetime """
|
|
35
|
+
key = ':'.join((self._prefix, dataset))
|
|
36
|
+
self._redis.set(key, 1)
|
|
37
|
+
self._redis.expire(key, self._timeout)
|
|
38
|
+
|
|
39
|
+
def check_dataset(self, dataset):
|
|
40
|
+
""" Checks if dataset is still in cache """
|
|
41
|
+
key = ':'.join((self._prefix, dataset))
|
|
42
|
+
if self._redis.get(key) is None:
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
return True
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
Utility classes for C3PO
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from collections import deque
|
|
21
|
+
from threading import Lock, Timer
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ExpiringList(object):
|
|
25
|
+
"""
|
|
26
|
+
Simple list with time based element expiration
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, timeout=1):
|
|
30
|
+
self._lock = Lock()
|
|
31
|
+
self._timeout = timeout
|
|
32
|
+
self._items = deque()
|
|
33
|
+
|
|
34
|
+
def add(self, item):
|
|
35
|
+
"""Add event time
|
|
36
|
+
"""
|
|
37
|
+
with self._lock:
|
|
38
|
+
self._items.append(item)
|
|
39
|
+
Timer(self._timeout, self._expire).start()
|
|
40
|
+
|
|
41
|
+
def __len__(self):
|
|
42
|
+
"""
|
|
43
|
+
Return number of active events
|
|
44
|
+
"""
|
|
45
|
+
with self._lock:
|
|
46
|
+
return len(self._items)
|
|
47
|
+
|
|
48
|
+
def _expire(self):
|
|
49
|
+
"""
|
|
50
|
+
Remove any expired events
|
|
51
|
+
"""
|
|
52
|
+
with self._lock:
|
|
53
|
+
self._items.popleft()
|
|
54
|
+
|
|
55
|
+
def to_set(self):
|
|
56
|
+
"""
|
|
57
|
+
Return items as a set
|
|
58
|
+
"""
|
|
59
|
+
return set(self._items)
|
|
60
|
+
|
|
61
|
+
def __str__(self):
|
|
62
|
+
with self._lock:
|
|
63
|
+
return str(self._items)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from json import dumps, loads
|
|
18
|
+
|
|
19
|
+
from requests import post
|
|
20
|
+
from requests.auth import HTTPBasicAuth
|
|
21
|
+
|
|
22
|
+
from rucio.common.config import config_get, config_get_options
|
|
23
|
+
|
|
24
|
+
ELASTIC_URL = config_get('es-atlas', 'url')
|
|
25
|
+
|
|
26
|
+
ELASTIC_OPTIONS = config_get_options('es-atlas')
|
|
27
|
+
|
|
28
|
+
AUTH = None
|
|
29
|
+
if ('username' in ELASTIC_OPTIONS) and ('password' in ELASTIC_OPTIONS):
|
|
30
|
+
AUTH = HTTPBasicAuth(config_get('es-atlas', 'username'), config_get('es-atlas', 'password'))
|
|
31
|
+
|
|
32
|
+
if 'ca_cert' in ELASTIC_OPTIONS:
|
|
33
|
+
ELASTIC_CA_CERT = config_get('es-atlas', 'ca_cert')
|
|
34
|
+
else:
|
|
35
|
+
ELASTIC_CA_CERT = False
|
|
36
|
+
|
|
37
|
+
URL = ELASTIC_URL + '/atlas_rucio-popularity-*/_search'
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_popularity(did):
|
|
41
|
+
"""
|
|
42
|
+
Query the popularity for a given DID in the ElasticSearch popularity db.
|
|
43
|
+
"""
|
|
44
|
+
query = {
|
|
45
|
+
"query": {
|
|
46
|
+
"bool": {
|
|
47
|
+
"must": [{
|
|
48
|
+
"range": {
|
|
49
|
+
"timestamp": {
|
|
50
|
+
"gt": "now-7d",
|
|
51
|
+
"lt": "now"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}]
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"aggs": {
|
|
58
|
+
"pop": {"sum": {"field": "ops"}}
|
|
59
|
+
},
|
|
60
|
+
"size": 0
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
query['query']['bool']['must'].append({"term": {"scope": did[0].external}})
|
|
64
|
+
query['query']['bool']['must'].append({"term": {"name": did[1]}})
|
|
65
|
+
|
|
66
|
+
logging.debug(query)
|
|
67
|
+
if AUTH:
|
|
68
|
+
res = post(URL, data=dumps(query), auth=AUTH, verify=ELASTIC_CA_CERT)
|
|
69
|
+
else:
|
|
70
|
+
res = post(URL, data=dumps(query), verify=ELASTIC_CA_CERT)
|
|
71
|
+
|
|
72
|
+
if res.status_code != 200:
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
result = loads(res.text)
|
|
76
|
+
|
|
77
|
+
if 'aggregations' in result:
|
|
78
|
+
if 'pop' in result['aggregations']:
|
|
79
|
+
if 'value' in result['aggregations']['pop']:
|
|
80
|
+
return result['aggregations']['pop']['value']
|
|
81
|
+
|
|
82
|
+
return None
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
Redis time series abstraction
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from time import time
|
|
21
|
+
|
|
22
|
+
from redis import StrictRedis
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RedisTimeSeries(object):
|
|
26
|
+
"""
|
|
27
|
+
Redis time series abstraction
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, redis_host, redis_port, window, prefix):
|
|
31
|
+
self._redis = StrictRedis(host=redis_host, port=redis_port)
|
|
32
|
+
self._prefix = prefix
|
|
33
|
+
self._window = window * 1000000
|
|
34
|
+
|
|
35
|
+
def add_point(self, key, value):
|
|
36
|
+
"""
|
|
37
|
+
Add a point
|
|
38
|
+
"""
|
|
39
|
+
r_key = self._prefix + key
|
|
40
|
+
score = int(time() * 1000000)
|
|
41
|
+
self._redis.zadd(r_key, score, "%d:%d" % (value, score))
|
|
42
|
+
|
|
43
|
+
def get_series(self, key):
|
|
44
|
+
"""
|
|
45
|
+
Return a time series tuple
|
|
46
|
+
"""
|
|
47
|
+
r_key = self._prefix + key
|
|
48
|
+
r_series = self._redis.zrange(r_key, 0, -1)
|
|
49
|
+
series = []
|
|
50
|
+
for val in r_series:
|
|
51
|
+
values, _ = val.split(':')
|
|
52
|
+
series.append(int(values))
|
|
53
|
+
|
|
54
|
+
return tuple(series)
|
|
55
|
+
|
|
56
|
+
def trim(self):
|
|
57
|
+
"""
|
|
58
|
+
Trim the time series
|
|
59
|
+
"""
|
|
60
|
+
now = time()
|
|
61
|
+
max_score = int(now * 1000000 - self._window)
|
|
62
|
+
for key in self.get_keys():
|
|
63
|
+
self._redis.zremrangebyscore(key, 0, max_score)
|
|
64
|
+
|
|
65
|
+
def get_keys(self):
|
|
66
|
+
"""
|
|
67
|
+
Return matching keys
|
|
68
|
+
"""
|
|
69
|
+
return self._redis.keys(pattern=self._prefix + "*")
|
|
70
|
+
|
|
71
|
+
def delete_keys(self):
|
|
72
|
+
"""
|
|
73
|
+
Delete keys
|
|
74
|
+
"""
|
|
75
|
+
for key in self.get_keys():
|
|
76
|
+
self._redis.zremrangebyrank(key, 0, -1)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
Cache consumer is a daemon to retrieve rucio cache operation information to synchronize rucio catalog.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import logging
|
|
22
|
+
import threading
|
|
23
|
+
import time
|
|
24
|
+
from traceback import format_exc
|
|
25
|
+
from typing import TYPE_CHECKING
|
|
26
|
+
|
|
27
|
+
import rucio.db.sqla.util
|
|
28
|
+
from rucio.common import exception
|
|
29
|
+
from rucio.common.config import config_get, config_get_int, config_get_bool, config_get_list
|
|
30
|
+
from rucio.common.logging import setup_logging, formatted_logger
|
|
31
|
+
from rucio.common.stomp_utils import StompConnectionManager
|
|
32
|
+
from rucio.common.types import InternalScope
|
|
33
|
+
from rucio.core.monitor import MetricManager
|
|
34
|
+
from rucio.core.rse import get_rse_id
|
|
35
|
+
from rucio.core.volatile_replica import add_volatile_replicas, delete_volatile_replicas
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from types import FrameType
|
|
39
|
+
from typing import Optional
|
|
40
|
+
|
|
41
|
+
logging.getLogger("stomp").setLevel(logging.CRITICAL)
|
|
42
|
+
|
|
43
|
+
METRICS = MetricManager(module=__name__)
|
|
44
|
+
GRACEFUL_STOP = threading.Event()
|
|
45
|
+
DAEMON_NAME = 'cache-consumer'
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class AMQConsumer(object):
|
|
49
|
+
"""
|
|
50
|
+
class Consumer
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(self, broker, conn, logger):
|
|
54
|
+
"""
|
|
55
|
+
__init__
|
|
56
|
+
"""
|
|
57
|
+
self.__broker = broker
|
|
58
|
+
self.__conn = conn
|
|
59
|
+
self.__logger = logger
|
|
60
|
+
|
|
61
|
+
@METRICS.count_it
|
|
62
|
+
def on_heartbeat_timeout(self):
|
|
63
|
+
self.__conn.disconnect()
|
|
64
|
+
|
|
65
|
+
@METRICS.count_it
|
|
66
|
+
def on_error(self, frame):
|
|
67
|
+
"""
|
|
68
|
+
on_error
|
|
69
|
+
"""
|
|
70
|
+
self.__logger(logging.ERROR, 'Message receive error: [%s] %s' % (self.__broker, frame.body))
|
|
71
|
+
|
|
72
|
+
@METRICS.count_it
|
|
73
|
+
def on_message(self, frame):
|
|
74
|
+
"""
|
|
75
|
+
on_message
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
msg = json.loads(frame.body)
|
|
79
|
+
self.__logger(logging.DEBUG, 'Message received: %s ' % msg)
|
|
80
|
+
if isinstance(msg, dict) and 'operation' in msg.keys():
|
|
81
|
+
for f in msg['files']:
|
|
82
|
+
f['scope'] = InternalScope(f['scope'])
|
|
83
|
+
if 'rse_id' in msg:
|
|
84
|
+
rse_id = msg['rse_id']
|
|
85
|
+
else:
|
|
86
|
+
rse_id = get_rse_id(rse=msg['rse'], vo=msg.get('vo', 'def'))
|
|
87
|
+
|
|
88
|
+
rse_vo_str = msg['rse']
|
|
89
|
+
if 'vo' in msg and msg['vo'] != 'def':
|
|
90
|
+
rse_vo_str = '{} on {}'.format(rse_vo_str, msg['vo'])
|
|
91
|
+
if msg['operation'] == 'add_replicas':
|
|
92
|
+
self.__logger(logging.INFO, 'add_replicas to RSE %s: %s ' % (rse_vo_str, str(msg['files'])))
|
|
93
|
+
add_volatile_replicas(rse_id=rse_id, replicas=msg['files'])
|
|
94
|
+
elif msg['operation'] == 'delete_replicas':
|
|
95
|
+
self.__logger(logging.INFO, 'delete_replicas to RSE %s: %s ' % (rse_vo_str, str(msg['files'])))
|
|
96
|
+
delete_volatile_replicas(rse_id=rse_id, replicas=msg['files'])
|
|
97
|
+
else:
|
|
98
|
+
self.__logger(logging.DEBUG, 'Check failed: %s %s '
|
|
99
|
+
% (isinstance(msg, dict), 'operation' in msg.keys()))
|
|
100
|
+
except:
|
|
101
|
+
self.__logger(logging.ERROR, str(format_exc()))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def consumer(id_, num_thread=1):
|
|
105
|
+
"""
|
|
106
|
+
Main loop to consume messages from the Rucio Cache producer.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
logger = formatted_logger(logging.log, DAEMON_NAME + ' %s')
|
|
110
|
+
|
|
111
|
+
logger(logging.INFO, 'Rucio Cache consumer starting')
|
|
112
|
+
|
|
113
|
+
brokers = config_get_list('messaging-cache', 'brokers')
|
|
114
|
+
|
|
115
|
+
use_ssl = config_get_bool('messaging-cache', 'use_ssl', default=True, raise_exception=False)
|
|
116
|
+
if not use_ssl:
|
|
117
|
+
username = config_get('messaging-cache', 'username')
|
|
118
|
+
password = config_get('messaging-cache', 'password')
|
|
119
|
+
destination = config_get('messaging-cache', 'destination')
|
|
120
|
+
subscription_id = 'rucio-cache-messaging'
|
|
121
|
+
|
|
122
|
+
vhost = config_get('messaging-cache', 'broker_virtual_host', raise_exception=False)
|
|
123
|
+
port = config_get_int('messaging-cache', 'port')
|
|
124
|
+
reconnect_attempts = config_get_int('messaging-cache', 'reconnect_attempts', default=100)
|
|
125
|
+
ssl_key_file = config_get('messaging-cache', 'ssl_key_file', raise_exception=False)
|
|
126
|
+
ssl_cert_file = config_get('messaging-cache', 'ssl_cert_file', raise_exception=False)
|
|
127
|
+
|
|
128
|
+
stomp_conn_mngr = StompConnectionManager()
|
|
129
|
+
conns, _ = stomp_conn_mngr.re_configure(
|
|
130
|
+
brokers=brokers,
|
|
131
|
+
port=port,
|
|
132
|
+
use_ssl=use_ssl,
|
|
133
|
+
vhost=vhost,
|
|
134
|
+
reconnect_attempts=reconnect_attempts,
|
|
135
|
+
ssl_key_file=ssl_key_file,
|
|
136
|
+
ssl_cert_file=ssl_cert_file,
|
|
137
|
+
timeout=None,
|
|
138
|
+
logger=logger
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
logger(logging.INFO, 'consumer started')
|
|
142
|
+
|
|
143
|
+
while not GRACEFUL_STOP.is_set():
|
|
144
|
+
for conn in conns:
|
|
145
|
+
if not conn.is_connected():
|
|
146
|
+
host_port = conn.transport._Transport__host_and_ports[0]
|
|
147
|
+
|
|
148
|
+
logger(logging.INFO, 'connecting to %s' % host_port[0])
|
|
149
|
+
METRICS.counter('reconnect.{host}').labels(host=host_port[0]).inc()
|
|
150
|
+
conn.set_listener('rucio-cache-consumer', AMQConsumer(broker=host_port, conn=conn, logger=logger))
|
|
151
|
+
if not use_ssl:
|
|
152
|
+
conn.connect(username, password)
|
|
153
|
+
else:
|
|
154
|
+
conn.connect()
|
|
155
|
+
|
|
156
|
+
conn.subscribe(destination=destination, ack='auto', id=subscription_id)
|
|
157
|
+
time.sleep(1)
|
|
158
|
+
|
|
159
|
+
logger(logging.INFO, 'graceful stop requested')
|
|
160
|
+
stomp_conn_mngr.disconnect()
|
|
161
|
+
logger(logging.INFO, 'graceful stop done')
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def stop(signum: "Optional[int]" = None, frame: "Optional[FrameType]" = None) -> None:
|
|
165
|
+
"""
|
|
166
|
+
Graceful exit.
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
GRACEFUL_STOP.set()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def run(num_thread=1):
|
|
173
|
+
"""
|
|
174
|
+
Starts up the rucio cache consumer thread
|
|
175
|
+
"""
|
|
176
|
+
setup_logging(process_name=DAEMON_NAME)
|
|
177
|
+
|
|
178
|
+
if rucio.db.sqla.util.is_old_db():
|
|
179
|
+
raise exception.DatabaseException('Database was not updated, daemon won\'t start')
|
|
180
|
+
|
|
181
|
+
logging.info('starting consumer thread')
|
|
182
|
+
threads = [threading.Thread(target=consumer, kwargs={'id_': i, 'num_thread': num_thread})
|
|
183
|
+
for i in range(0, num_thread)]
|
|
184
|
+
|
|
185
|
+
[t.start() for t in threads]
|
|
186
|
+
|
|
187
|
+
logging.info('waiting for interrupts')
|
|
188
|
+
|
|
189
|
+
# Interruptible joins require a timeout.
|
|
190
|
+
while threads[0].is_alive():
|
|
191
|
+
[t.join(timeout=3.14) for t in threads]
|