rucio 32.8.6__py3-none-any.whl → 35.8.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 +0 -1
- rucio/alembicrevision.py +1 -2
- rucio/client/__init__.py +0 -1
- rucio/client/accountclient.py +45 -25
- rucio/client/accountlimitclient.py +37 -9
- rucio/client/baseclient.py +199 -154
- rucio/client/client.py +2 -3
- rucio/client/configclient.py +19 -6
- rucio/client/credentialclient.py +9 -4
- rucio/client/didclient.py +238 -63
- rucio/client/diracclient.py +13 -5
- rucio/client/downloadclient.py +162 -51
- rucio/client/exportclient.py +4 -4
- rucio/client/fileclient.py +3 -4
- rucio/client/importclient.py +4 -4
- rucio/client/lifetimeclient.py +21 -5
- rucio/client/lockclient.py +18 -8
- rucio/client/{metaclient.py → metaconventionsclient.py} +18 -15
- rucio/client/pingclient.py +0 -1
- rucio/client/replicaclient.py +15 -5
- rucio/client/requestclient.py +35 -19
- rucio/client/rseclient.py +133 -51
- rucio/client/ruleclient.py +29 -22
- rucio/client/scopeclient.py +8 -6
- rucio/client/subscriptionclient.py +47 -35
- rucio/client/touchclient.py +8 -4
- rucio/client/uploadclient.py +166 -82
- rucio/common/__init__.py +0 -1
- rucio/common/cache.py +4 -4
- rucio/common/config.py +52 -47
- rucio/common/constants.py +69 -2
- rucio/common/constraints.py +0 -1
- rucio/common/didtype.py +24 -22
- rucio/common/dumper/__init__.py +70 -41
- rucio/common/dumper/consistency.py +26 -22
- rucio/common/dumper/data_models.py +16 -23
- rucio/common/dumper/path_parsing.py +0 -1
- rucio/common/exception.py +281 -222
- rucio/common/extra.py +0 -1
- rucio/common/logging.py +54 -38
- rucio/common/pcache.py +122 -101
- rucio/common/plugins.py +153 -0
- rucio/common/policy.py +4 -4
- rucio/common/schema/__init__.py +17 -10
- rucio/common/schema/atlas.py +7 -5
- rucio/common/schema/belleii.py +7 -5
- rucio/common/schema/domatpc.py +7 -5
- rucio/common/schema/escape.py +7 -5
- rucio/common/schema/generic.py +8 -6
- rucio/common/schema/generic_multi_vo.py +7 -5
- rucio/common/schema/icecube.py +7 -5
- rucio/common/stomp_utils.py +0 -1
- rucio/common/stopwatch.py +0 -1
- rucio/common/test_rucio_server.py +2 -2
- rucio/common/types.py +262 -17
- rucio/common/utils.py +743 -451
- rucio/core/__init__.py +0 -1
- rucio/core/account.py +99 -29
- rucio/core/account_counter.py +89 -24
- rucio/core/account_limit.py +90 -24
- rucio/core/authentication.py +86 -29
- rucio/core/config.py +108 -38
- rucio/core/credential.py +14 -7
- rucio/core/did.py +680 -782
- rucio/core/did_meta_plugins/__init__.py +8 -6
- rucio/core/did_meta_plugins/did_column_meta.py +17 -12
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +60 -11
- rucio/core/did_meta_plugins/filter_engine.py +90 -50
- rucio/core/did_meta_plugins/json_meta.py +41 -16
- rucio/core/did_meta_plugins/mongo_meta.py +25 -8
- rucio/core/did_meta_plugins/postgres_meta.py +3 -4
- rucio/core/dirac.py +46 -17
- rucio/core/distance.py +66 -43
- rucio/core/exporter.py +5 -5
- rucio/core/heartbeat.py +181 -81
- rucio/core/identity.py +22 -12
- rucio/core/importer.py +23 -12
- rucio/core/lifetime_exception.py +32 -32
- rucio/core/lock.py +244 -142
- rucio/core/message.py +79 -38
- rucio/core/{meta.py → meta_conventions.py} +57 -44
- rucio/core/monitor.py +19 -13
- rucio/core/naming_convention.py +68 -27
- rucio/core/nongrid_trace.py +17 -5
- rucio/core/oidc.py +151 -29
- rucio/core/permission/__init__.py +18 -6
- rucio/core/permission/atlas.py +50 -35
- rucio/core/permission/belleii.py +6 -5
- rucio/core/permission/escape.py +8 -6
- rucio/core/permission/generic.py +82 -80
- rucio/core/permission/generic_multi_vo.py +9 -7
- rucio/core/quarantined_replica.py +91 -58
- rucio/core/replica.py +1303 -772
- rucio/core/replica_sorter.py +10 -12
- rucio/core/request.py +1133 -285
- rucio/core/rse.py +142 -102
- rucio/core/rse_counter.py +49 -18
- rucio/core/rse_expression_parser.py +6 -7
- rucio/core/rse_selector.py +41 -16
- rucio/core/rule.py +1538 -474
- rucio/core/rule_grouping.py +213 -68
- rucio/core/scope.py +50 -22
- rucio/core/subscription.py +92 -44
- rucio/core/topology.py +66 -24
- rucio/core/trace.py +42 -28
- rucio/core/transfer.py +543 -259
- rucio/core/vo.py +36 -18
- rucio/core/volatile_replica.py +59 -32
- rucio/daemons/__init__.py +0 -1
- rucio/daemons/abacus/__init__.py +0 -1
- rucio/daemons/abacus/account.py +29 -19
- rucio/daemons/abacus/collection_replica.py +21 -10
- rucio/daemons/abacus/rse.py +22 -12
- rucio/daemons/atropos/__init__.py +0 -1
- rucio/daemons/atropos/atropos.py +1 -2
- rucio/daemons/auditor/__init__.py +56 -28
- rucio/daemons/auditor/hdfs.py +17 -6
- rucio/daemons/auditor/srmdumps.py +116 -45
- rucio/daemons/automatix/__init__.py +0 -1
- rucio/daemons/automatix/automatix.py +30 -18
- rucio/daemons/badreplicas/__init__.py +0 -1
- rucio/daemons/badreplicas/minos.py +29 -18
- rucio/daemons/badreplicas/minos_temporary_expiration.py +5 -7
- rucio/daemons/badreplicas/necromancer.py +9 -13
- rucio/daemons/bb8/__init__.py +0 -1
- rucio/daemons/bb8/bb8.py +10 -13
- rucio/daemons/bb8/common.py +151 -154
- rucio/daemons/bb8/nuclei_background_rebalance.py +15 -9
- rucio/daemons/bb8/t2_background_rebalance.py +15 -8
- rucio/daemons/c3po/__init__.py +0 -1
- rucio/daemons/c3po/algorithms/__init__.py +0 -1
- rucio/daemons/c3po/algorithms/simple.py +8 -5
- rucio/daemons/c3po/algorithms/t2_free_space.py +10 -7
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +10 -7
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +30 -15
- rucio/daemons/c3po/c3po.py +81 -52
- rucio/daemons/c3po/collectors/__init__.py +0 -1
- rucio/daemons/c3po/collectors/agis.py +17 -17
- rucio/daemons/c3po/collectors/free_space.py +32 -13
- rucio/daemons/c3po/collectors/jedi_did.py +14 -5
- rucio/daemons/c3po/collectors/mock_did.py +11 -6
- rucio/daemons/c3po/collectors/network_metrics.py +12 -4
- rucio/daemons/c3po/collectors/workload.py +21 -19
- rucio/daemons/c3po/utils/__init__.py +0 -1
- rucio/daemons/c3po/utils/dataset_cache.py +15 -5
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +16 -5
- rucio/daemons/c3po/utils/expiring_list.py +6 -7
- rucio/daemons/c3po/utils/popularity.py +5 -2
- rucio/daemons/c3po/utils/timeseries.py +25 -12
- rucio/daemons/cache/__init__.py +0 -1
- rucio/daemons/cache/consumer.py +21 -15
- rucio/daemons/common.py +42 -18
- rucio/daemons/conveyor/__init__.py +0 -1
- rucio/daemons/conveyor/common.py +69 -37
- rucio/daemons/conveyor/finisher.py +83 -46
- rucio/daemons/conveyor/poller.py +101 -69
- rucio/daemons/conveyor/preparer.py +35 -28
- rucio/daemons/conveyor/receiver.py +64 -21
- rucio/daemons/conveyor/stager.py +33 -28
- rucio/daemons/conveyor/submitter.py +71 -47
- rucio/daemons/conveyor/throttler.py +99 -35
- rucio/daemons/follower/__init__.py +0 -1
- rucio/daemons/follower/follower.py +12 -8
- rucio/daemons/hermes/__init__.py +0 -1
- rucio/daemons/hermes/hermes.py +57 -21
- rucio/daemons/judge/__init__.py +0 -1
- rucio/daemons/judge/cleaner.py +27 -17
- rucio/daemons/judge/evaluator.py +31 -18
- rucio/daemons/judge/injector.py +31 -23
- rucio/daemons/judge/repairer.py +28 -18
- rucio/daemons/oauthmanager/__init__.py +0 -1
- rucio/daemons/oauthmanager/oauthmanager.py +7 -8
- rucio/daemons/reaper/__init__.py +0 -1
- rucio/daemons/reaper/dark_reaper.py +15 -9
- rucio/daemons/reaper/reaper.py +109 -67
- rucio/daemons/replicarecoverer/__init__.py +0 -1
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +255 -116
- rucio/{api → daemons/rsedecommissioner}/__init__.py +0 -1
- 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 +0 -1
- rucio/daemons/storage/consistency/__init__.py +0 -1
- rucio/daemons/storage/consistency/actions.py +152 -59
- rucio/daemons/tracer/__init__.py +0 -1
- rucio/daemons/tracer/kronos.py +47 -24
- rucio/daemons/transmogrifier/__init__.py +0 -1
- rucio/daemons/transmogrifier/transmogrifier.py +35 -26
- rucio/daemons/undertaker/__init__.py +0 -1
- rucio/daemons/undertaker/undertaker.py +10 -10
- rucio/db/__init__.py +0 -1
- rucio/db/sqla/__init__.py +16 -2
- rucio/db/sqla/constants.py +10 -1
- rucio/db/sqla/migrate_repo/__init__.py +0 -1
- rucio/db/sqla/migrate_repo/env.py +0 -1
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +0 -1
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +1 -3
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +0 -3
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +1 -4
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +0 -1
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +0 -2
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +0 -2
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +0 -3
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +0 -1
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +1 -2
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +0 -1
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +0 -3
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +1 -4
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +0 -2
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +0 -3
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +1 -2
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +0 -1
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +0 -1
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +0 -2
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +0 -2
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +1 -4
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +1 -4
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +0 -1
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +1 -3
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +0 -2
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +1 -3
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +1 -2
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +1 -3
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +0 -2
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +2 -3
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +1 -4
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +0 -1
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +0 -1
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +0 -1
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +0 -2
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +0 -3
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +0 -2
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +2 -4
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +0 -2
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +1 -4
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +0 -2
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +0 -3
- 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 +0 -2
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +0 -2
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +0 -3
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +0 -3
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +1 -3
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +1 -3
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +0 -3
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +1 -2
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +2 -4
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +0 -1
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +1 -4
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +0 -2
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +1 -2
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +0 -3
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +1 -3
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +0 -3
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +0 -1
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +0 -2
- 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 +1 -3
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +0 -2
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +1 -4
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +0 -1
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +0 -1
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +1 -4
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +0 -1
- 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 +0 -3
- 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 +1 -2
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +1 -3
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +1 -5
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +1 -3
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +0 -3
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +1 -3
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +0 -3
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +1 -4
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +1 -2
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +1 -4
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +1 -3
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +1 -4
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +0 -2
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +1 -3
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +0 -1
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +1 -2
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +1 -3
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +0 -2
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +0 -1
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +1 -2
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +0 -3
- rucio/db/sqla/models.py +122 -216
- rucio/db/sqla/sautils.py +12 -5
- rucio/db/sqla/session.py +71 -43
- rucio/db/sqla/types.py +3 -4
- rucio/db/sqla/util.py +91 -69
- rucio/gateway/__init__.py +13 -0
- rucio/{api → gateway}/account.py +119 -46
- rucio/{api → gateway}/account_limit.py +12 -13
- rucio/{api → gateway}/authentication.py +106 -33
- rucio/{api → gateway}/config.py +12 -13
- rucio/{api → gateway}/credential.py +15 -4
- rucio/{api → gateway}/did.py +384 -140
- rucio/{api → gateway}/dirac.py +16 -6
- rucio/{api → gateway}/exporter.py +3 -4
- rucio/{api → gateway}/heartbeat.py +17 -5
- rucio/{api → gateway}/identity.py +63 -19
- rucio/{api → gateway}/importer.py +3 -4
- rucio/{api → gateway}/lifetime_exception.py +35 -10
- rucio/{api → gateway}/lock.py +34 -12
- rucio/{api/meta.py → gateway/meta_conventions.py} +18 -16
- rucio/{api → gateway}/permission.py +4 -5
- rucio/{api → gateway}/quarantined_replica.py +13 -4
- rucio/{api → gateway}/replica.py +12 -11
- rucio/{api → gateway}/request.py +129 -28
- rucio/{api → gateway}/rse.py +11 -12
- rucio/{api → gateway}/rule.py +117 -35
- rucio/{api → gateway}/scope.py +24 -14
- rucio/{api → gateway}/subscription.py +65 -43
- rucio/{api → gateway}/vo.py +17 -7
- rucio/rse/__init__.py +3 -4
- rucio/rse/protocols/__init__.py +0 -1
- rucio/rse/protocols/bittorrent.py +184 -0
- rucio/rse/protocols/cache.py +1 -2
- rucio/rse/protocols/dummy.py +1 -2
- rucio/rse/protocols/gfal.py +12 -10
- rucio/rse/protocols/globus.py +7 -7
- rucio/rse/protocols/gsiftp.py +2 -3
- rucio/rse/protocols/http_cache.py +1 -2
- rucio/rse/protocols/mock.py +1 -2
- rucio/rse/protocols/ngarc.py +1 -2
- rucio/rse/protocols/posix.py +12 -13
- rucio/rse/protocols/protocol.py +116 -52
- rucio/rse/protocols/rclone.py +6 -7
- rucio/rse/protocols/rfio.py +4 -5
- rucio/rse/protocols/srm.py +9 -10
- rucio/rse/protocols/ssh.py +8 -9
- rucio/rse/protocols/storm.py +2 -3
- rucio/rse/protocols/webdav.py +17 -14
- rucio/rse/protocols/xrootd.py +23 -17
- rucio/rse/rsemanager.py +19 -7
- rucio/tests/__init__.py +0 -1
- rucio/tests/common.py +43 -17
- rucio/tests/common_server.py +3 -3
- rucio/transfertool/__init__.py +0 -1
- 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 +250 -138
- rucio/transfertool/fts3_plugins.py +152 -0
- rucio/transfertool/globus.py +9 -8
- rucio/transfertool/globus_library.py +1 -2
- rucio/transfertool/mock.py +21 -12
- rucio/transfertool/transfertool.py +33 -24
- rucio/vcsversion.py +4 -4
- rucio/version.py +5 -13
- rucio/web/__init__.py +0 -1
- rucio/web/rest/__init__.py +0 -1
- rucio/web/rest/flaskapi/__init__.py +0 -1
- rucio/web/rest/flaskapi/authenticated_bp.py +0 -1
- rucio/web/rest/flaskapi/v1/__init__.py +0 -1
- rucio/web/rest/flaskapi/v1/accountlimits.py +15 -13
- rucio/web/rest/flaskapi/v1/accounts.py +49 -48
- rucio/web/rest/flaskapi/v1/archives.py +12 -10
- rucio/web/rest/flaskapi/v1/auth.py +146 -144
- rucio/web/rest/flaskapi/v1/common.py +82 -41
- rucio/web/rest/flaskapi/v1/config.py +5 -6
- rucio/web/rest/flaskapi/v1/credentials.py +7 -8
- rucio/web/rest/flaskapi/v1/dids.py +158 -28
- rucio/web/rest/flaskapi/v1/dirac.py +8 -8
- rucio/web/rest/flaskapi/v1/export.py +3 -5
- rucio/web/rest/flaskapi/v1/heartbeats.py +3 -5
- rucio/web/rest/flaskapi/v1/identities.py +3 -5
- rucio/web/rest/flaskapi/v1/import.py +3 -4
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +6 -9
- rucio/web/rest/flaskapi/v1/locks.py +2 -4
- rucio/web/rest/flaskapi/v1/main.py +10 -2
- rucio/web/rest/flaskapi/v1/{meta.py → meta_conventions.py} +26 -11
- rucio/web/rest/flaskapi/v1/metrics.py +1 -2
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +4 -4
- rucio/web/rest/flaskapi/v1/ping.py +6 -7
- rucio/web/rest/flaskapi/v1/redirect.py +8 -9
- rucio/web/rest/flaskapi/v1/replicas.py +43 -19
- rucio/web/rest/flaskapi/v1/requests.py +178 -21
- rucio/web/rest/flaskapi/v1/rses.py +61 -26
- rucio/web/rest/flaskapi/v1/rules.py +48 -18
- rucio/web/rest/flaskapi/v1/scopes.py +3 -5
- rucio/web/rest/flaskapi/v1/subscriptions.py +22 -18
- rucio/web/rest/flaskapi/v1/traces.py +4 -4
- rucio/web/rest/flaskapi/v1/types.py +20 -0
- rucio/web/rest/flaskapi/v1/vos.py +3 -5
- rucio/web/rest/main.py +0 -1
- rucio/web/rest/metrics.py +0 -1
- rucio/web/rest/ping.py +27 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/ldap.cfg.template +1 -1
- rucio-35.8.0.data/data/rucio/requirements.server.txt +268 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/bootstrap.py +3 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/merge_rucio_configs.py +2 -5
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/reset_database.py +3 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio +87 -85
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-account +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-collection-replica +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-rse +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-admin +45 -32
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-atropos +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-auditor +13 -7
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-automatix +1 -2
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-bb8 +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-c3po +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-client +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-consumer +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-finisher +1 -2
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-poller +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-preparer +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-receiver +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-stager +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-submitter +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-throttler +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dark-reaper +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dumper +11 -10
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-follower +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-hermes +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-cleaner +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-evaluator +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-injector +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-repairer +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-kronos +1 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos-temporary-expiration +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-necromancer +1 -2
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-oauth-manager +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-reaper +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-replica-recoverer +6 -7
- rucio-35.8.0.data/scripts/rucio-rse-decommissioner +66 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-storage-consistency-actions +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-transmogrifier +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-undertaker +1 -2
- rucio-35.8.0.dist-info/METADATA +72 -0
- rucio-35.8.0.dist-info/RECORD +493 -0
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/WHEEL +1 -1
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/AUTHORS.rst +3 -0
- rucio/api/temporary_did.py +0 -49
- rucio/common/schema/cms.py +0 -478
- rucio/common/schema/lsst.py +0 -423
- rucio/core/permission/cms.py +0 -1166
- rucio/core/temporary_did.py +0 -188
- rucio/daemons/reaper/light_reaper.py +0 -255
- rucio/web/rest/flaskapi/v1/tmp_dids.py +0 -115
- rucio-32.8.6.data/data/rucio/requirements.txt +0 -55
- rucio-32.8.6.data/scripts/rucio-light-reaper +0 -53
- rucio-32.8.6.dist-info/METADATA +0 -83
- rucio-32.8.6.dist-info/RECORD +0 -481
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic.ini.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/LICENSE +0 -0
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/top_level.txt +0 -0
rucio/core/rse.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -14,28 +13,28 @@
|
|
|
14
13
|
# limitations under the License.
|
|
15
14
|
|
|
16
15
|
import json
|
|
17
|
-
from collections.abc import
|
|
16
|
+
from collections.abc import Iterable, Iterator
|
|
18
17
|
from datetime import datetime
|
|
19
18
|
from io import StringIO
|
|
20
19
|
from re import match
|
|
21
|
-
from typing import Any, Generic, Optional, TypeVar, Union
|
|
20
|
+
from typing import TYPE_CHECKING, Any, Generic, Optional, TypeVar, Union
|
|
22
21
|
|
|
23
22
|
import sqlalchemy
|
|
24
23
|
from dogpile.cache.api import NO_VALUE
|
|
25
24
|
from sqlalchemy.exc import DatabaseError, IntegrityError, OperationalError
|
|
26
25
|
from sqlalchemy.orm import aliased
|
|
27
26
|
from sqlalchemy.orm.exc import FlushError
|
|
28
|
-
from sqlalchemy.sql.expression import
|
|
27
|
+
from sqlalchemy.sql.expression import and_, delete, desc, false, func, or_, select, true
|
|
29
28
|
|
|
30
|
-
from rucio.common import exception, utils
|
|
29
|
+
from rucio.common import exception, types, utils
|
|
31
30
|
from rucio.common.cache import make_region_memcached
|
|
32
31
|
from rucio.common.config import get_lfn2pfn_algorithm_default
|
|
33
|
-
from rucio.common import
|
|
32
|
+
from rucio.common.constants import RSE_SUPPORTED_PROTOCOL_OPERATIONS, RseAttr
|
|
34
33
|
from rucio.common.utils import CHECKSUM_KEY, GLOBALLY_SUPPORTED_CHECKSUMS, Availability
|
|
35
34
|
from rucio.core.rse_counter import add_counter, get_counter
|
|
36
35
|
from rucio.db.sqla import models
|
|
37
|
-
from rucio.db.sqla.constants import
|
|
38
|
-
from rucio.db.sqla.session import read_session,
|
|
36
|
+
from rucio.db.sqla.constants import ReplicaState, RSEType
|
|
37
|
+
from rucio.db.sqla.session import read_session, stream_session, transactional_session
|
|
39
38
|
from rucio.db.sqla.util import temp_table_mngr
|
|
40
39
|
|
|
41
40
|
if TYPE_CHECKING:
|
|
@@ -84,7 +83,7 @@ class RseData:
|
|
|
84
83
|
return self._attributes
|
|
85
84
|
|
|
86
85
|
@property
|
|
87
|
-
def info(self) ->
|
|
86
|
+
def info(self) -> types.RSESettingsDict:
|
|
88
87
|
if self._info is None:
|
|
89
88
|
raise ValueError(f'info not loaded for rse {self}')
|
|
90
89
|
return self._info
|
|
@@ -121,12 +120,12 @@ class RseData:
|
|
|
121
120
|
return self.id == other.id
|
|
122
121
|
|
|
123
122
|
def is_tape(self):
|
|
124
|
-
if self.info['rse_type'] == RSEType.TAPE or self.info['rse_type'] == 'TAPE':
|
|
123
|
+
if self.info['rse_type'] == RSEType.TAPE or self.info['rse_type'] == 'TAPE' or self.attributes.get(RseAttr.STAGING_REQUIRED, False):
|
|
125
124
|
return True
|
|
126
125
|
return False
|
|
127
126
|
|
|
128
127
|
def is_tape_or_staging_required(self):
|
|
129
|
-
if self.is_tape() or self.attributes.get(
|
|
128
|
+
if self.is_tape() or self.attributes.get(RseAttr.STAGING_REQUIRED, False):
|
|
130
129
|
return True
|
|
131
130
|
return False
|
|
132
131
|
|
|
@@ -153,8 +152,18 @@ class RseData:
|
|
|
153
152
|
|
|
154
153
|
@staticmethod
|
|
155
154
|
@read_session
|
|
156
|
-
def bulk_load(
|
|
157
|
-
|
|
155
|
+
def bulk_load(
|
|
156
|
+
rse_id_to_data: "dict[str, RseData]",
|
|
157
|
+
load_name: bool = False,
|
|
158
|
+
load_columns: bool = False,
|
|
159
|
+
load_attributes: bool = False,
|
|
160
|
+
load_info: bool = False,
|
|
161
|
+
load_usage: bool = False,
|
|
162
|
+
load_limits: bool = False,
|
|
163
|
+
include_deleted: bool = False,
|
|
164
|
+
*,
|
|
165
|
+
session: "Session"
|
|
166
|
+
):
|
|
158
167
|
"""
|
|
159
168
|
Given a dict of RseData objects indexed by rse_id, ensure that the desired fields are initialised
|
|
160
169
|
in all objects from the input.
|
|
@@ -195,16 +204,18 @@ class RseData:
|
|
|
195
204
|
# query, but this seems wasteful under normal operation: the caller of the current function probably
|
|
196
205
|
# got the list of RSE IDs from list_rses (or another source which checks for deleted rses).
|
|
197
206
|
#
|
|
198
|
-
# Instead, directly fetch all RSEs, which allows to reduce the number (and complexity) of other queries
|
|
207
|
+
# Instead, directly fetch all RSEs, which allows to reduce the number (and complexity) of other queries below
|
|
199
208
|
stmt = select(
|
|
200
209
|
models.RSE
|
|
201
210
|
).join_from(
|
|
202
211
|
temp_table,
|
|
203
212
|
models.RSE,
|
|
204
213
|
models.RSE.id == temp_table.id
|
|
205
|
-
).where(
|
|
206
|
-
models.RSE.deleted == false()
|
|
207
214
|
)
|
|
215
|
+
if not include_deleted:
|
|
216
|
+
stmt = stmt.where(
|
|
217
|
+
models.RSE.deleted == false()
|
|
218
|
+
)
|
|
208
219
|
db_rses_by_id = {str(db_rse.id): db_rse for db_rse in session.execute(stmt).scalars()}
|
|
209
220
|
|
|
210
221
|
if len(db_rses_by_id) != len(rse_ids_to_load):
|
|
@@ -231,11 +242,11 @@ class RseData:
|
|
|
231
242
|
if load_info:
|
|
232
243
|
stmt = select(
|
|
233
244
|
temp_table.id,
|
|
234
|
-
models.
|
|
245
|
+
models.RSEProtocol
|
|
235
246
|
).outerjoin_from(
|
|
236
247
|
temp_table,
|
|
237
|
-
models.
|
|
238
|
-
models.
|
|
248
|
+
models.RSEProtocol,
|
|
249
|
+
models.RSEProtocol.rse_id == temp_table.id
|
|
239
250
|
).order_by(
|
|
240
251
|
temp_table.id,
|
|
241
252
|
)
|
|
@@ -330,6 +341,7 @@ class RseCollection(Generic[T]):
|
|
|
330
341
|
load_info: bool = False,
|
|
331
342
|
load_usage: bool = False,
|
|
332
343
|
load_limits: bool = False,
|
|
344
|
+
include_deleted: bool = False,
|
|
333
345
|
*,
|
|
334
346
|
session: "Session",
|
|
335
347
|
):
|
|
@@ -341,6 +353,7 @@ class RseCollection(Generic[T]):
|
|
|
341
353
|
load_info=load_info,
|
|
342
354
|
load_usage=load_usage,
|
|
343
355
|
load_limits=load_limits,
|
|
356
|
+
include_deleted=include_deleted,
|
|
344
357
|
session=session,
|
|
345
358
|
)
|
|
346
359
|
|
|
@@ -446,10 +459,8 @@ def rse_exists(rse, vo='def', include_deleted=False, *, session: "Session"):
|
|
|
446
459
|
stmt = select(
|
|
447
460
|
models.RSE
|
|
448
461
|
).where(
|
|
449
|
-
and_(
|
|
450
|
-
|
|
451
|
-
models.RSE.vo == vo
|
|
452
|
-
)
|
|
462
|
+
and_(models.RSE.rse == rse,
|
|
463
|
+
models.RSE.vo == vo)
|
|
453
464
|
)
|
|
454
465
|
if not include_deleted:
|
|
455
466
|
stmt = stmt.where(models.RSE.deleted == false())
|
|
@@ -469,8 +480,8 @@ def del_rse(rse_id, *, session: "Session"):
|
|
|
469
480
|
stmt = select(
|
|
470
481
|
models.RSE
|
|
471
482
|
).where(
|
|
472
|
-
models.RSE.id == rse_id,
|
|
473
|
-
|
|
483
|
+
and_(models.RSE.id == rse_id,
|
|
484
|
+
models.RSE.deleted == false())
|
|
474
485
|
)
|
|
475
486
|
db_rse = session.execute(stmt).scalar_one()
|
|
476
487
|
rse_name = db_rse.rse
|
|
@@ -498,8 +509,8 @@ def restore_rse(rse_id, *, session: "Session"):
|
|
|
498
509
|
stmt = select(
|
|
499
510
|
models.RSE
|
|
500
511
|
).where(
|
|
501
|
-
models.RSE.id == rse_id,
|
|
502
|
-
|
|
512
|
+
and_(models.RSE.id == rse_id,
|
|
513
|
+
models.RSE.deleted == true())
|
|
503
514
|
)
|
|
504
515
|
db_rse = session.execute(stmt).scalar_one()
|
|
505
516
|
except sqlalchemy.orm.exc.NoResultFound:
|
|
@@ -565,13 +576,14 @@ def get_rse(rse_id, *, session: "Session"):
|
|
|
565
576
|
:raises RSENotFound: If referred RSE was not found in the database.
|
|
566
577
|
"""
|
|
567
578
|
|
|
568
|
-
false_value = False # To make pep8 checker happy ...
|
|
569
579
|
try:
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
.
|
|
574
|
-
|
|
580
|
+
stmt = select(
|
|
581
|
+
models.RSE
|
|
582
|
+
).where(
|
|
583
|
+
and_(models.RSE.deleted == false(),
|
|
584
|
+
models.RSE.id == rse_id)
|
|
585
|
+
)
|
|
586
|
+
return _format_get_rse(session.execute(stmt).scalar_one(), session=session)
|
|
575
587
|
except sqlalchemy.orm.exc.NoResultFound:
|
|
576
588
|
raise exception.RSENotFound('RSE with id \'%s\' cannot be found' % rse_id)
|
|
577
589
|
|
|
@@ -603,8 +615,8 @@ def get_rse_id(rse, vo='def', include_deleted=True, *, session: "Session"):
|
|
|
603
615
|
stmt = select(
|
|
604
616
|
models.RSE.id
|
|
605
617
|
).where(
|
|
606
|
-
models.RSE.rse == rse,
|
|
607
|
-
|
|
618
|
+
and_(models.RSE.rse == rse,
|
|
619
|
+
models.RSE.vo == vo)
|
|
608
620
|
)
|
|
609
621
|
if not include_deleted:
|
|
610
622
|
stmt = stmt.where(models.RSE.deleted == false())
|
|
@@ -687,7 +699,7 @@ def get_rse_vo(rse_id: str, include_deleted: bool = True, *, session: "Session")
|
|
|
687
699
|
|
|
688
700
|
|
|
689
701
|
@read_session
|
|
690
|
-
def list_rses(filters=
|
|
702
|
+
def list_rses(filters: Optional[dict[str, Any]] = None, *, session: "Session") -> list[dict[str, Any]]:
|
|
691
703
|
"""
|
|
692
704
|
Returns a list of all RSEs.
|
|
693
705
|
|
|
@@ -697,7 +709,7 @@ def list_rses(filters={}, *, session: "Session"):
|
|
|
697
709
|
:returns: a list of dictionaries.
|
|
698
710
|
"""
|
|
699
711
|
|
|
700
|
-
|
|
712
|
+
filters = filters or {}
|
|
701
713
|
filters = filters.copy() # Make a copy, so we can pop() without affecting the object `filters` outside this function
|
|
702
714
|
|
|
703
715
|
stmt = select(
|
|
@@ -726,21 +738,15 @@ def list_rses(filters={}, *, session: "Session"):
|
|
|
726
738
|
attr_assoc_alias = aliased(models.RSEAttrAssociation)
|
|
727
739
|
stmt = stmt.join(
|
|
728
740
|
attr_assoc_alias,
|
|
729
|
-
and_(
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
attr_assoc_alias.value == v,
|
|
733
|
-
)
|
|
741
|
+
and_(attr_assoc_alias.rse_id == models.RSE.id,
|
|
742
|
+
attr_assoc_alias.key == k,
|
|
743
|
+
attr_assoc_alias.value == v)
|
|
734
744
|
)
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
)
|
|
739
|
-
|
|
740
|
-
for row in session.execute(stmt).scalars():
|
|
741
|
-
rse_list.append(row.to_dict())
|
|
745
|
+
stmt = stmt.order_by(
|
|
746
|
+
models.RSE.rse
|
|
747
|
+
)
|
|
742
748
|
|
|
743
|
-
return
|
|
749
|
+
return [row.to_dict() for row in session.execute(stmt).scalars()]
|
|
744
750
|
|
|
745
751
|
|
|
746
752
|
@transactional_session
|
|
@@ -780,8 +786,8 @@ def del_rse_attribute(rse_id, key, *, session: "Session"):
|
|
|
780
786
|
stmt = select(
|
|
781
787
|
models.RSEAttrAssociation
|
|
782
788
|
).where(
|
|
783
|
-
models.RSEAttrAssociation.rse_id == rse_id,
|
|
784
|
-
|
|
789
|
+
and_(models.RSEAttrAssociation.rse_id == rse_id,
|
|
790
|
+
models.RSEAttrAssociation.key == key)
|
|
785
791
|
)
|
|
786
792
|
rse_attr = session.execute(stmt).scalar_one()
|
|
787
793
|
except sqlalchemy.orm.exc.NoResultFound:
|
|
@@ -870,8 +876,8 @@ def has_rse_attribute(rse_id, key, *, session: "Session"):
|
|
|
870
876
|
stmt = select(
|
|
871
877
|
models.RSEAttrAssociation.value
|
|
872
878
|
).where(
|
|
873
|
-
models.RSEAttrAssociation.rse_id == rse_id,
|
|
874
|
-
|
|
879
|
+
and_(models.RSEAttrAssociation.rse_id == rse_id,
|
|
880
|
+
models.RSEAttrAssociation.key == key)
|
|
875
881
|
)
|
|
876
882
|
if session.execute(stmt).scalar():
|
|
877
883
|
return True
|
|
@@ -896,10 +902,8 @@ def get_rses_with_attribute(key, *, session: "Session"):
|
|
|
896
902
|
models.RSE.deleted == false()
|
|
897
903
|
).join(
|
|
898
904
|
models.RSEAttrAssociation,
|
|
899
|
-
and_(
|
|
900
|
-
|
|
901
|
-
models.RSEAttrAssociation.key == key
|
|
902
|
-
)
|
|
905
|
+
and_(models.RSEAttrAssociation.rse_id == models.RSE.id,
|
|
906
|
+
models.RSEAttrAssociation.key == key)
|
|
903
907
|
)
|
|
904
908
|
|
|
905
909
|
for db_rse in session.execute(stmt).scalars():
|
|
@@ -933,15 +937,13 @@ def get_rses_with_attribute_value(key, value, vo='def', *, session: "Session"):
|
|
|
933
937
|
models.RSE.id,
|
|
934
938
|
models.RSE.rse,
|
|
935
939
|
).where(
|
|
936
|
-
models.RSE.deleted == false(),
|
|
937
|
-
|
|
940
|
+
and_(models.RSE.deleted == false(),
|
|
941
|
+
models.RSE.vo == vo)
|
|
938
942
|
).join(
|
|
939
943
|
models.RSEAttrAssociation,
|
|
940
|
-
and_(
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
models.RSEAttrAssociation.value == value
|
|
944
|
-
)
|
|
944
|
+
and_(models.RSEAttrAssociation.rse_id == models.RSE.id,
|
|
945
|
+
models.RSEAttrAssociation.key == key,
|
|
946
|
+
models.RSEAttrAssociation.value == value)
|
|
945
947
|
)
|
|
946
948
|
|
|
947
949
|
for row in session.execute(stmt):
|
|
@@ -979,8 +981,8 @@ def get_rse_attribute(rse_id: str, key: str, use_cache: bool = True, *, session:
|
|
|
979
981
|
stmt = select(
|
|
980
982
|
models.RSEAttrAssociation.value
|
|
981
983
|
).where(
|
|
982
|
-
models.RSEAttrAssociation.rse_id == rse_id,
|
|
983
|
-
|
|
984
|
+
and_(models.RSEAttrAssociation.rse_id == rse_id,
|
|
985
|
+
models.RSEAttrAssociation.key == key)
|
|
984
986
|
)
|
|
985
987
|
value = session.execute(stmt).scalar_one_or_none()
|
|
986
988
|
|
|
@@ -1199,10 +1201,8 @@ def get_rse_transfer_limits(rse_id, activity=None, *, session: "Session"):
|
|
|
1199
1201
|
)
|
|
1200
1202
|
if activity:
|
|
1201
1203
|
stmt = stmt.where(
|
|
1202
|
-
or_(
|
|
1203
|
-
models.TransferLimit.activity ==
|
|
1204
|
-
models.TransferLimit.activity == 'all_activities',
|
|
1205
|
-
)
|
|
1204
|
+
or_(models.TransferLimit.activity == activity,
|
|
1205
|
+
models.TransferLimit.activity == 'all_activities')
|
|
1206
1206
|
)
|
|
1207
1207
|
|
|
1208
1208
|
limits = {}
|
|
@@ -1255,7 +1255,7 @@ def add_protocol(
|
|
|
1255
1255
|
parameter: dict[str, Any],
|
|
1256
1256
|
*,
|
|
1257
1257
|
session: "Session"
|
|
1258
|
-
) -> models.
|
|
1258
|
+
) -> models.RSEProtocol:
|
|
1259
1259
|
"""
|
|
1260
1260
|
Add a protocol to an existing RSE.
|
|
1261
1261
|
|
|
@@ -1289,7 +1289,7 @@ def add_protocol(
|
|
|
1289
1289
|
if domain not in utils.rse_supported_protocol_domains():
|
|
1290
1290
|
raise exception.RSEProtocolDomainNotSupported(f"The protocol domain '{domain}' is not defined in the schema.")
|
|
1291
1291
|
for op in parameter['domains'][domain]:
|
|
1292
|
-
if op not in
|
|
1292
|
+
if op not in RSE_SUPPORTED_PROTOCOL_OPERATIONS:
|
|
1293
1293
|
raise exception.RSEOperationNotSupported(f"Operation '{op}' not defined in schema.")
|
|
1294
1294
|
op_name = op if op.startswith('third_party_copy') else f'{op}_{domain}'.lower()
|
|
1295
1295
|
priority = parameter['domains'][domain][op]
|
|
@@ -1309,7 +1309,7 @@ def add_protocol(
|
|
|
1309
1309
|
raise exception.InvalidObject('Missing values! For SRM, extended_attributes and web_service_path must be specified')
|
|
1310
1310
|
|
|
1311
1311
|
try:
|
|
1312
|
-
new_protocol = models.
|
|
1312
|
+
new_protocol = models.RSEProtocol()
|
|
1313
1313
|
new_protocol.update(parameter)
|
|
1314
1314
|
new_protocol.save(session=session)
|
|
1315
1315
|
except (IntegrityError, FlushError, OperationalError) as error:
|
|
@@ -1351,14 +1351,14 @@ def get_rse_protocols(rse_id, schemes=None, *, session: "Session") -> types.RSES
|
|
|
1351
1351
|
if not _rse:
|
|
1352
1352
|
raise exception.RSENotFound('RSE with id \'%s\' not found' % rse_id)
|
|
1353
1353
|
|
|
1354
|
-
terms = [models.
|
|
1354
|
+
terms = [models.RSEProtocol.rse_id == rse_id]
|
|
1355
1355
|
if schemes:
|
|
1356
1356
|
if not type(schemes) is list:
|
|
1357
1357
|
schemes = [schemes]
|
|
1358
|
-
terms.extend([models.
|
|
1358
|
+
terms.extend([models.RSEProtocol.scheme.in_(schemes)])
|
|
1359
1359
|
|
|
1360
1360
|
stmt = select(
|
|
1361
|
-
models.
|
|
1361
|
+
models.RSEProtocol
|
|
1362
1362
|
).where(
|
|
1363
1363
|
*terms
|
|
1364
1364
|
)
|
|
@@ -1369,16 +1369,16 @@ def get_rse_protocols(rse_id, schemes=None, *, session: "Session") -> types.RSES
|
|
|
1369
1369
|
|
|
1370
1370
|
def _format_get_rse_protocols(
|
|
1371
1371
|
rse: "models.RSE | dict[str, Any]",
|
|
1372
|
-
db_protocols: Iterable[models.
|
|
1372
|
+
db_protocols: Iterable[models.RSEProtocol],
|
|
1373
1373
|
rse_attributes: Optional[dict[str, Any]] = None,
|
|
1374
1374
|
*,
|
|
1375
1375
|
session: "Session"
|
|
1376
1376
|
) -> types.RSESettingsDict:
|
|
1377
1377
|
_rse = rse
|
|
1378
1378
|
if rse_attributes:
|
|
1379
|
-
lfn2pfn_algorithm = rse_attributes.get(
|
|
1379
|
+
lfn2pfn_algorithm = rse_attributes.get(RseAttr.LFN2PFN_ALGORITHM)
|
|
1380
1380
|
else:
|
|
1381
|
-
lfn2pfn_algorithm = get_rse_attribute(_rse['id'],
|
|
1381
|
+
lfn2pfn_algorithm = get_rse_attribute(_rse['id'], RseAttr.LFN2PFN_ALGORITHM, session=session)
|
|
1382
1382
|
# Resolve LFN2PFN default algorithm as soon as possible. This way, we can send back the actual
|
|
1383
1383
|
# algorithm name in response to REST queries.
|
|
1384
1384
|
if not lfn2pfn_algorithm:
|
|
@@ -1386,15 +1386,15 @@ def _format_get_rse_protocols(
|
|
|
1386
1386
|
|
|
1387
1387
|
# Copy verify_checksum from the attributes, later: assume True if not specified
|
|
1388
1388
|
if rse_attributes:
|
|
1389
|
-
verify_checksum = rse_attributes.get(
|
|
1389
|
+
verify_checksum = rse_attributes.get(RseAttr.VERIFY_CHECKSUM)
|
|
1390
1390
|
else:
|
|
1391
|
-
verify_checksum = get_rse_attribute(_rse['id'],
|
|
1391
|
+
verify_checksum = get_rse_attribute(_rse['id'], RseAttr.VERIFY_CHECKSUM, session=session)
|
|
1392
1392
|
|
|
1393
1393
|
# Copy sign_url from the attributes
|
|
1394
1394
|
if rse_attributes:
|
|
1395
|
-
sign_url = rse_attributes.get(
|
|
1395
|
+
sign_url = rse_attributes.get(RseAttr.SIGN_URL)
|
|
1396
1396
|
else:
|
|
1397
|
-
sign_url = get_rse_attribute(_rse['id'],
|
|
1397
|
+
sign_url = get_rse_attribute(_rse['id'], RseAttr.SIGN_URL, session=session)
|
|
1398
1398
|
|
|
1399
1399
|
info = {'availability_delete': _rse['availability_delete'],
|
|
1400
1400
|
'availability_read': _rse['availability_read'],
|
|
@@ -1413,7 +1413,7 @@ def _format_get_rse_protocols(
|
|
|
1413
1413
|
'verify_checksum': verify_checksum if verify_checksum is not None else True,
|
|
1414
1414
|
'volatile': _rse['volatile']}
|
|
1415
1415
|
|
|
1416
|
-
for op in
|
|
1416
|
+
for op in RSE_SUPPORTED_PROTOCOL_OPERATIONS:
|
|
1417
1417
|
info['%s_protocol' % op] = 1 # 1 indicates the default protocol
|
|
1418
1418
|
|
|
1419
1419
|
for row in db_protocols:
|
|
@@ -1500,7 +1500,7 @@ def update_protocols(
|
|
|
1500
1500
|
if domain not in utils.rse_supported_protocol_domains():
|
|
1501
1501
|
raise exception.RSEProtocolDomainNotSupported(f"The protocol domain '{domain}' is not defined in the schema.")
|
|
1502
1502
|
for op in data['domains'][domain]:
|
|
1503
|
-
if op not in
|
|
1503
|
+
if op not in RSE_SUPPORTED_PROTOCOL_OPERATIONS:
|
|
1504
1504
|
raise exception.RSEOperationNotSupported(f"Operation '{op}' not defined in schema.")
|
|
1505
1505
|
op_name = op if op.startswith('third_party_copy') else f'{op}_{domain}'.lower()
|
|
1506
1506
|
priority = data['domains'][domain][op]
|
|
@@ -1520,14 +1520,14 @@ def update_protocols(
|
|
|
1520
1520
|
except exception.RSENotFound:
|
|
1521
1521
|
raise exception.RSENotFound('RSE with id \'%s\' not found' % rse_id)
|
|
1522
1522
|
|
|
1523
|
-
terms = [models.
|
|
1524
|
-
models.
|
|
1525
|
-
models.
|
|
1526
|
-
models.
|
|
1523
|
+
terms = [models.RSEProtocol.rse_id == rse_id,
|
|
1524
|
+
models.RSEProtocol.scheme == scheme,
|
|
1525
|
+
models.RSEProtocol.hostname == hostname,
|
|
1526
|
+
models.RSEProtocol.port == port]
|
|
1527
1527
|
|
|
1528
1528
|
try:
|
|
1529
1529
|
stmt = select(
|
|
1530
|
-
models.
|
|
1530
|
+
models.RSEProtocol
|
|
1531
1531
|
).where(
|
|
1532
1532
|
*terms
|
|
1533
1533
|
)
|
|
@@ -1575,13 +1575,13 @@ def del_protocols(
|
|
|
1575
1575
|
rse_name = get_rse_name(rse_id=rse_id, session=session, include_deleted=False)
|
|
1576
1576
|
except exception.RSENotFound:
|
|
1577
1577
|
raise exception.RSENotFound('RSE \'%s\' not found' % rse_id)
|
|
1578
|
-
terms = [models.
|
|
1578
|
+
terms = [models.RSEProtocol.rse_id == rse_id, models.RSEProtocol.scheme == scheme]
|
|
1579
1579
|
if hostname is not None:
|
|
1580
|
-
terms.append(models.
|
|
1580
|
+
terms.append(models.RSEProtocol.hostname == hostname)
|
|
1581
1581
|
if port is not None:
|
|
1582
|
-
terms.append(models.
|
|
1582
|
+
terms.append(models.RSEProtocol.port == port)
|
|
1583
1583
|
stmt = select(
|
|
1584
|
-
models.
|
|
1584
|
+
models.RSEProtocol
|
|
1585
1585
|
).where(
|
|
1586
1586
|
*terms
|
|
1587
1587
|
)
|
|
@@ -1771,8 +1771,8 @@ def delete_qos_policy(rse_id, qos_policy, *, session: "Session"):
|
|
|
1771
1771
|
stmt = delete(
|
|
1772
1772
|
models.RSEQoSAssociation
|
|
1773
1773
|
).where(
|
|
1774
|
-
models.RSEQoSAssociation.rse_id == rse_id,
|
|
1775
|
-
|
|
1774
|
+
and_(models.RSEQoSAssociation.rse_id == rse_id,
|
|
1775
|
+
models.RSEQoSAssociation.qos_policy == qos_policy)
|
|
1776
1776
|
)
|
|
1777
1777
|
session.execute(stmt)
|
|
1778
1778
|
except DatabaseError as error:
|
|
@@ -1820,12 +1820,14 @@ def fill_rse_expired(rse_id, *, session: "Session"):
|
|
|
1820
1820
|
func.sum(models.RSEFileAssociation.bytes).label("bytes"),
|
|
1821
1821
|
func.count().label("length")
|
|
1822
1822
|
).with_hint(
|
|
1823
|
-
models.RSEFileAssociation,
|
|
1823
|
+
models.RSEFileAssociation,
|
|
1824
|
+
'INDEX(REPLICAS REPLICAS_RSE_ID_TOMBSTONE_IDX)',
|
|
1825
|
+
'oracle'
|
|
1824
1826
|
).where(
|
|
1825
|
-
models.RSEFileAssociation.tombstone < datetime.utcnow(),
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1827
|
+
and_(models.RSEFileAssociation.tombstone < datetime.utcnow(),
|
|
1828
|
+
models.RSEFileAssociation.lock_cnt == 0,
|
|
1829
|
+
models.RSEFileAssociation.rse_id == rse_id,
|
|
1830
|
+
models.RSEFileAssociation.state.in_((ReplicaState.AVAILABLE, ReplicaState.UNAVAILABLE, ReplicaState.BAD)))
|
|
1829
1831
|
)
|
|
1830
1832
|
|
|
1831
1833
|
sum_bytes, sum_files = session.execute(stmt).one()
|
|
@@ -1833,3 +1835,41 @@ def fill_rse_expired(rse_id, *, session: "Session"):
|
|
|
1833
1835
|
used=sum_bytes,
|
|
1834
1836
|
files=sum_files,
|
|
1835
1837
|
source='expired').save(session=session)
|
|
1838
|
+
|
|
1839
|
+
|
|
1840
|
+
def determine_audience_for_rse(rse_id: str) -> str:
|
|
1841
|
+
"""Construct the Audience claim for an RSE."""
|
|
1842
|
+
rse_protocols = get_rse_protocols(rse_id)
|
|
1843
|
+
# FIXME: At the time of writing, there does not appear to be a common
|
|
1844
|
+
# agreement on how sites will configure their storages. Rucio had requested
|
|
1845
|
+
# that the protocol hostname be sufficient, but this may not come to pass.
|
|
1846
|
+
filtered_hostnames = {p['hostname']
|
|
1847
|
+
for p in rse_protocols['protocols']
|
|
1848
|
+
if p['scheme'] == 'davs'}
|
|
1849
|
+
return ' '.join(sorted(filtered_hostnames))
|
|
1850
|
+
|
|
1851
|
+
|
|
1852
|
+
def determine_scope_for_rse(
|
|
1853
|
+
rse_id: str,
|
|
1854
|
+
scopes: Iterable[str],
|
|
1855
|
+
extra_scopes: Optional[Iterable[str]] = None,
|
|
1856
|
+
) -> str:
|
|
1857
|
+
"""Construct the Scope claim for an RSE."""
|
|
1858
|
+
if extra_scopes is None:
|
|
1859
|
+
extra_scopes = []
|
|
1860
|
+
rse_protocols = get_rse_protocols(rse_id)
|
|
1861
|
+
filtered_prefixes = set()
|
|
1862
|
+
for protocol in rse_protocols['protocols']:
|
|
1863
|
+
# Token support is exclusive to WebDAV.
|
|
1864
|
+
if protocol['scheme'] != 'davs':
|
|
1865
|
+
continue
|
|
1866
|
+
# Remove base path from prefix. Storages typically map an issuer (i.e.
|
|
1867
|
+
# a VO) to a particular area. If so, then the path to that area acts as
|
|
1868
|
+
# a base which should be removed from the prefix (in order for '/' to
|
|
1869
|
+
# mean the entire resource associated with that issuer).
|
|
1870
|
+
prefix = protocol['prefix']
|
|
1871
|
+
if base_path := get_rse_attribute(rse_id, RseAttr.OIDC_BASE_PATH):
|
|
1872
|
+
prefix = prefix.removeprefix(base_path)
|
|
1873
|
+
filtered_prefixes.add(prefix)
|
|
1874
|
+
all_scopes = [f'{s}:{p}' for s in scopes for p in filtered_prefixes] + list(extra_scopes)
|
|
1875
|
+
return ' '.join(sorted(all_scopes))
|
rucio/core/rse_counter.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -14,10 +13,11 @@
|
|
|
14
13
|
# limitations under the License.
|
|
15
14
|
from typing import TYPE_CHECKING
|
|
16
15
|
|
|
17
|
-
from sqlalchemy
|
|
16
|
+
from sqlalchemy import and_, delete, select
|
|
17
|
+
from sqlalchemy.exc import NoResultFound
|
|
18
18
|
|
|
19
19
|
from rucio.common.exception import CounterNotFound
|
|
20
|
-
from rucio.db.sqla import
|
|
20
|
+
from rucio.db.sqla import filter_thread_work, models
|
|
21
21
|
from rucio.db.sqla.session import read_session, transactional_session
|
|
22
22
|
|
|
23
23
|
if TYPE_CHECKING:
|
|
@@ -72,8 +72,15 @@ def del_counter(rse_id, *, session: "Session"):
|
|
|
72
72
|
:param session: The database session in use.
|
|
73
73
|
"""
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
stmt = delete(
|
|
76
|
+
models.RSEUsage
|
|
77
|
+
).where(
|
|
78
|
+
and_(models.RSEUsage.rse_id == rse_id,
|
|
79
|
+
models.RSEUsage.source == 'rucio')
|
|
80
|
+
).execution_options(
|
|
81
|
+
synchronize_session=False
|
|
82
|
+
)
|
|
83
|
+
session.execute(stmt)
|
|
77
84
|
|
|
78
85
|
|
|
79
86
|
@read_session
|
|
@@ -89,11 +96,20 @@ def get_counter(rse_id, *, session: "Session"):
|
|
|
89
96
|
"""
|
|
90
97
|
|
|
91
98
|
try:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
stmt = select(
|
|
100
|
+
models.RSEUsage.used,
|
|
101
|
+
models.RSEUsage.files,
|
|
102
|
+
models.RSEUsage.updated_at
|
|
103
|
+
).where(
|
|
104
|
+
and_(models.RSEUsage.rse_id == rse_id,
|
|
105
|
+
models.RSEUsage.source == 'rucio')
|
|
106
|
+
)
|
|
107
|
+
usage_bytes, usage_files, usage_updated_at = session.execute(stmt).one()
|
|
108
|
+
return {
|
|
109
|
+
'bytes': usage_bytes,
|
|
110
|
+
'files': usage_files,
|
|
111
|
+
'updated_at': usage_updated_at
|
|
112
|
+
}
|
|
97
113
|
except NoResultFound:
|
|
98
114
|
raise CounterNotFound()
|
|
99
115
|
|
|
@@ -108,12 +124,13 @@ def get_updated_rse_counters(total_workers, worker_number, *, session: "Session"
|
|
|
108
124
|
:param session: Database session in use.
|
|
109
125
|
:returns: List of rse_ids whose rse_counters need to be updated.
|
|
110
126
|
"""
|
|
111
|
-
|
|
112
|
-
|
|
127
|
+
stmt = select(
|
|
128
|
+
models.UpdatedRSECounter.rse_id
|
|
129
|
+
).distinct(
|
|
130
|
+
)
|
|
113
131
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return [result.rse_id for result in results]
|
|
132
|
+
stmt = filter_thread_work(session=session, query=stmt, total_threads=total_workers, thread_id=worker_number, hash_variable='rse_id')
|
|
133
|
+
return session.execute(stmt).scalars().all()
|
|
117
134
|
|
|
118
135
|
|
|
119
136
|
@transactional_session
|
|
@@ -125,12 +142,23 @@ def update_rse_counter(rse_id, *, session: "Session"):
|
|
|
125
142
|
:param session: Database session in use.
|
|
126
143
|
"""
|
|
127
144
|
|
|
128
|
-
|
|
145
|
+
stmt = select(
|
|
146
|
+
models.UpdatedRSECounter
|
|
147
|
+
).where(
|
|
148
|
+
models.UpdatedRSECounter.rse_id == rse_id
|
|
149
|
+
)
|
|
150
|
+
updated_rse_counters = session.execute(stmt).scalars().all()
|
|
129
151
|
sum_bytes = sum([updated_rse_counter.bytes for updated_rse_counter in updated_rse_counters])
|
|
130
152
|
sum_files = sum([updated_rse_counter.files for updated_rse_counter in updated_rse_counters])
|
|
131
153
|
|
|
132
154
|
try:
|
|
133
|
-
|
|
155
|
+
stmt = select(
|
|
156
|
+
models.RSEUsage
|
|
157
|
+
).where(
|
|
158
|
+
and_(models.RSEUsage.rse_id == rse_id,
|
|
159
|
+
models.RSEUsage.source == 'rucio')
|
|
160
|
+
)
|
|
161
|
+
rse_counter = session.execute(stmt).scalar_one()
|
|
134
162
|
rse_counter.used = (rse_counter.used or 0) + sum_bytes
|
|
135
163
|
rse_counter.files = (rse_counter.files or 0) + sum_files
|
|
136
164
|
except NoResultFound:
|
|
@@ -151,5 +179,8 @@ def fill_rse_counter_history_table(*, session: "Session"):
|
|
|
151
179
|
:param session: Database session in use.
|
|
152
180
|
"""
|
|
153
181
|
RSEUsageHistory = models.RSEUsageHistory
|
|
154
|
-
|
|
182
|
+
stmt = select(
|
|
183
|
+
models.RSEUsage
|
|
184
|
+
)
|
|
185
|
+
for usage in session.execute(stmt).scalars().all():
|
|
155
186
|
RSEUsageHistory(rse_id=usage['rse_id'], used=usage['used'], files=usage['files'], source=usage['source']).save(session=session)
|