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/account_limit.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");
|
|
@@ -15,8 +14,8 @@
|
|
|
15
14
|
|
|
16
15
|
from typing import TYPE_CHECKING
|
|
17
16
|
|
|
18
|
-
from sqlalchemy.
|
|
19
|
-
from sqlalchemy.sql import func,
|
|
17
|
+
from sqlalchemy.exc import NoResultFound
|
|
18
|
+
from sqlalchemy.sql import func, literal, select
|
|
20
19
|
from sqlalchemy.sql.expression import and_, or_
|
|
21
20
|
|
|
22
21
|
from rucio.core.account import get_all_rse_usages_per_account
|
|
@@ -99,9 +98,17 @@ def get_global_account_limits(account=None, *, session: "Session"):
|
|
|
99
98
|
:return: Dict {'MOCK': {'resolved_rses': ['MOCK'], 'limit': 10, 'resolved_rse_ids': [123]}}.
|
|
100
99
|
"""
|
|
101
100
|
if account:
|
|
102
|
-
|
|
101
|
+
stmt = select(
|
|
102
|
+
models.AccountGlobalLimit
|
|
103
|
+
).where(
|
|
104
|
+
models.AccountGlobalLimit.account == account
|
|
105
|
+
)
|
|
106
|
+
global_account_limits = session.execute(stmt).scalars().all()
|
|
103
107
|
else:
|
|
104
|
-
|
|
108
|
+
stmt = select(
|
|
109
|
+
models.AccountGlobalLimit
|
|
110
|
+
)
|
|
111
|
+
global_account_limits = session.execute(stmt).scalars().all()
|
|
105
112
|
|
|
106
113
|
resolved_global_account_limits = {}
|
|
107
114
|
for limit in global_account_limits:
|
|
@@ -131,7 +138,13 @@ def get_global_account_limit(account, rse_expression, *, session: "Session"):
|
|
|
131
138
|
:return: Limit in Bytes.
|
|
132
139
|
"""
|
|
133
140
|
try:
|
|
134
|
-
|
|
141
|
+
stmt = select(
|
|
142
|
+
models.AccountGlobalLimit
|
|
143
|
+
).where(
|
|
144
|
+
and_(models.AccountGlobalLimit.account == account,
|
|
145
|
+
models.AccountGlobalLimit.rse_expression == rse_expression)
|
|
146
|
+
)
|
|
147
|
+
global_account_limit = session.execute(stmt).scalar_one()
|
|
135
148
|
if global_account_limit.bytes == -1:
|
|
136
149
|
return float("inf")
|
|
137
150
|
else:
|
|
@@ -151,8 +164,13 @@ def get_local_account_limit(account, rse_id, *, session: "Session"):
|
|
|
151
164
|
:return: Limit in Bytes.
|
|
152
165
|
"""
|
|
153
166
|
try:
|
|
154
|
-
|
|
155
|
-
|
|
167
|
+
stmt = select(
|
|
168
|
+
models.AccountLimit
|
|
169
|
+
).where(
|
|
170
|
+
and_(models.AccountLimit.account == account,
|
|
171
|
+
models.AccountLimit.rse_id == rse_id)
|
|
172
|
+
)
|
|
173
|
+
account_limit = session.execute(stmt).scalar_one()
|
|
156
174
|
if account_limit.bytes == -1:
|
|
157
175
|
return float("inf")
|
|
158
176
|
else:
|
|
@@ -176,17 +194,28 @@ def get_local_account_limits(account, rse_ids=None, *, session: "Session"):
|
|
|
176
194
|
if rse_ids:
|
|
177
195
|
rse_id_clauses = []
|
|
178
196
|
for rse_id in rse_ids:
|
|
179
|
-
rse_id_clauses.append(and_(models.AccountLimit.rse_id == rse_id,
|
|
197
|
+
rse_id_clauses.append(and_(models.AccountLimit.rse_id == rse_id,
|
|
198
|
+
models.AccountLimit.account == account))
|
|
180
199
|
rse_id_clause_chunks = [rse_id_clauses[x:x + 10] for x in range(0, len(rse_id_clauses), 10)]
|
|
181
200
|
for rse_id_chunk in rse_id_clause_chunks:
|
|
182
|
-
|
|
201
|
+
stmt = select(
|
|
202
|
+
models.AccountLimit
|
|
203
|
+
).where(
|
|
204
|
+
or_(*rse_id_chunk)
|
|
205
|
+
)
|
|
206
|
+
tmp_limits = session.execute(stmt).scalars().all()
|
|
183
207
|
for limit in tmp_limits:
|
|
184
208
|
if limit.bytes == -1:
|
|
185
209
|
account_limits[limit.rse_id] = float("inf")
|
|
186
210
|
else:
|
|
187
211
|
account_limits[limit.rse_id] = limit.bytes
|
|
188
212
|
else:
|
|
189
|
-
|
|
213
|
+
stmt = select(
|
|
214
|
+
models.AccountLimit
|
|
215
|
+
).where(
|
|
216
|
+
models.AccountLimit.account == account
|
|
217
|
+
)
|
|
218
|
+
account_limits_tmp = session.execute(stmt).scalars().all()
|
|
190
219
|
for limit in account_limits_tmp:
|
|
191
220
|
if limit.bytes == -1:
|
|
192
221
|
account_limits[limit.rse_id] = float("inf")
|
|
@@ -206,8 +235,13 @@ def set_local_account_limit(account, rse_id, bytes_, *, session: "Session"):
|
|
|
206
235
|
:param session: Database session in use.
|
|
207
236
|
"""
|
|
208
237
|
try:
|
|
209
|
-
|
|
210
|
-
|
|
238
|
+
stmt = select(
|
|
239
|
+
models.AccountLimit
|
|
240
|
+
).where(
|
|
241
|
+
and_(models.AccountLimit.account == account,
|
|
242
|
+
models.AccountLimit.rse_id == rse_id)
|
|
243
|
+
)
|
|
244
|
+
account_limit = session.execute(stmt).scalar_one()
|
|
211
245
|
account_limit.bytes = bytes_
|
|
212
246
|
except NoResultFound:
|
|
213
247
|
models.AccountLimit(account=account, rse_id=rse_id, bytes=bytes_).save(session=session)
|
|
@@ -224,8 +258,13 @@ def set_global_account_limit(account, rse_expression, bytes_, *, session: "Sessi
|
|
|
224
258
|
:param session: Database session in use.
|
|
225
259
|
"""
|
|
226
260
|
try:
|
|
227
|
-
|
|
228
|
-
|
|
261
|
+
stmt = select(
|
|
262
|
+
models.AccountGlobalLimit
|
|
263
|
+
).where(
|
|
264
|
+
and_(models.AccountGlobalLimit.account == account,
|
|
265
|
+
models.AccountGlobalLimit.rse_expression == rse_expression)
|
|
266
|
+
)
|
|
267
|
+
account_limit = session.execute(stmt).scalar_one()
|
|
229
268
|
account_limit.bytes = bytes_
|
|
230
269
|
except NoResultFound:
|
|
231
270
|
models.AccountGlobalLimit(account=account, rse_expression=rse_expression, bytes=bytes_).save(session=session)
|
|
@@ -242,8 +281,14 @@ def delete_local_account_limit(account, rse_id, *, session: "Session"):
|
|
|
242
281
|
:returns: True if something was deleted; False otherwise.
|
|
243
282
|
"""
|
|
244
283
|
try:
|
|
245
|
-
|
|
246
|
-
|
|
284
|
+
stmt = select(
|
|
285
|
+
models.AccountLimit
|
|
286
|
+
).where(
|
|
287
|
+
and_(models.AccountLimit.account == account,
|
|
288
|
+
models.AccountLimit.rse_id == rse_id)
|
|
289
|
+
)
|
|
290
|
+
result = session.execute(stmt).scalar_one()
|
|
291
|
+
result.delete(session=session)
|
|
247
292
|
return True
|
|
248
293
|
except NoResultFound:
|
|
249
294
|
return False
|
|
@@ -260,8 +305,14 @@ def delete_global_account_limit(account, rse_expression, *, session: "Session"):
|
|
|
260
305
|
:returns: True if something was deleted; False otherwise.
|
|
261
306
|
"""
|
|
262
307
|
try:
|
|
263
|
-
|
|
264
|
-
|
|
308
|
+
stmt = select(
|
|
309
|
+
models.AccountGlobalLimit
|
|
310
|
+
).where(
|
|
311
|
+
and_(models.AccountGlobalLimit.account == account,
|
|
312
|
+
models.AccountGlobalLimit.rse_expression == rse_expression)
|
|
313
|
+
)
|
|
314
|
+
result = session.execute(stmt).scalar_one()
|
|
315
|
+
result.delete(session=session)
|
|
265
316
|
return True
|
|
266
317
|
except NoResultFound:
|
|
267
318
|
return False
|
|
@@ -279,14 +330,22 @@ def get_local_account_usage(account, rse_id=None, *, session: "Session"):
|
|
|
279
330
|
:returns: List of dicts {'rse_id', 'rse', 'bytes', 'files', 'bytes_limit', 'bytes_remaining'}
|
|
280
331
|
"""
|
|
281
332
|
|
|
333
|
+
stmt = select(
|
|
334
|
+
models.AccountUsage
|
|
335
|
+
).where(
|
|
336
|
+
models.AccountUsage.account == account
|
|
337
|
+
)
|
|
282
338
|
if not rse_id:
|
|
283
339
|
# All RSESs
|
|
284
340
|
limits = get_local_account_limits(account=account, session=session)
|
|
285
|
-
counters = {c.rse_id: c for c in session.
|
|
341
|
+
counters = {c.rse_id: c for c in session.execute(stmt).scalars().all()}
|
|
286
342
|
else:
|
|
287
343
|
# One RSE
|
|
344
|
+
stmt.where(
|
|
345
|
+
models.AccountUsage.rse_id == rse_id
|
|
346
|
+
)
|
|
288
347
|
limits = get_local_account_limits(account=account, rse_ids=[rse_id], session=session)
|
|
289
|
-
counters = {c.rse_id: c for c in session.
|
|
348
|
+
counters = {c.rse_id: c for c in session.execute(stmt).scalars().all()}
|
|
290
349
|
result_list = []
|
|
291
350
|
|
|
292
351
|
for rse_id in set(limits).union(counters):
|
|
@@ -341,9 +400,16 @@ def get_global_account_usage(account, rse_expression=None, *, session: "Session"
|
|
|
341
400
|
limit = get_global_account_limit(account=account, rse_expression=rse_expression, session=session)
|
|
342
401
|
vo = account.vo
|
|
343
402
|
resolved_rses = [resolved_rse['id'] for resolved_rse in parse_expression(rse_expression, filter_={'vo': vo}, session=session)]
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
403
|
+
stmt = select(
|
|
404
|
+
func.sum(models.AccountUsage.bytes),
|
|
405
|
+
func.sum(models.AccountUsage.files)
|
|
406
|
+
).where(
|
|
407
|
+
and_(models.AccountUsage.account == account,
|
|
408
|
+
models.AccountUsage.rse_id.in_(resolved_rses))
|
|
409
|
+
).group_by(
|
|
410
|
+
models.AccountUsage.account
|
|
411
|
+
)
|
|
412
|
+
usage = session.execute(stmt).first()
|
|
347
413
|
if limit is None:
|
|
348
414
|
limit = 0
|
|
349
415
|
if usage is None:
|
rucio/core/authentication.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");
|
|
@@ -20,27 +19,27 @@ import re
|
|
|
20
19
|
import sys
|
|
21
20
|
import traceback
|
|
22
21
|
from base64 import b64decode
|
|
23
|
-
from typing import TYPE_CHECKING
|
|
22
|
+
from typing import TYPE_CHECKING, Optional, Union, cast
|
|
24
23
|
|
|
25
24
|
import paramiko
|
|
26
25
|
from dogpile.cache import make_region
|
|
27
|
-
from dogpile.cache.api import NO_VALUE
|
|
26
|
+
from dogpile.cache.api import NO_VALUE, NoValue
|
|
28
27
|
from sqlalchemy import delete, null, or_, select
|
|
29
28
|
|
|
30
29
|
from rucio.common.cache import make_region_memcached
|
|
31
30
|
from rucio.common.config import config_get_bool
|
|
32
31
|
from rucio.common.exception import CannotAuthenticate, RucioException
|
|
33
|
-
from rucio.common.utils import chunks,
|
|
32
|
+
from rucio.common.utils import chunks, date_to_str, generate_uuid
|
|
34
33
|
from rucio.core.account import account_exists
|
|
35
34
|
from rucio.core.oidc import validate_jwt
|
|
36
|
-
from rucio.db.sqla import filter_thread_work
|
|
37
|
-
from rucio.db.sqla import models
|
|
35
|
+
from rucio.db.sqla import filter_thread_work, models
|
|
38
36
|
from rucio.db.sqla.constants import IdentityType
|
|
39
37
|
from rucio.db.sqla.session import read_session, transactional_session
|
|
40
38
|
|
|
41
39
|
if TYPE_CHECKING:
|
|
42
40
|
from sqlalchemy.orm import Session
|
|
43
|
-
|
|
41
|
+
|
|
42
|
+
from rucio.common.types import InternalAccount, TokenDict, TokenValidationDict
|
|
44
43
|
|
|
45
44
|
|
|
46
45
|
def strip_x509_proxy_attributes(dn: str) -> str:
|
|
@@ -90,7 +89,15 @@ else:
|
|
|
90
89
|
|
|
91
90
|
|
|
92
91
|
@transactional_session
|
|
93
|
-
def get_auth_token_user_pass(
|
|
92
|
+
def get_auth_token_user_pass(
|
|
93
|
+
account: "InternalAccount",
|
|
94
|
+
username: str,
|
|
95
|
+
password: str,
|
|
96
|
+
appid: str,
|
|
97
|
+
ip: Optional[str] = None,
|
|
98
|
+
*,
|
|
99
|
+
session: "Session"
|
|
100
|
+
) -> Optional["TokenDict"]:
|
|
94
101
|
"""
|
|
95
102
|
Authenticate a Rucio account temporarily via username and password.
|
|
96
103
|
|
|
@@ -150,7 +157,14 @@ def get_auth_token_user_pass(account, username, password, appid, ip=None, *, ses
|
|
|
150
157
|
|
|
151
158
|
|
|
152
159
|
@transactional_session
|
|
153
|
-
def get_auth_token_x509(
|
|
160
|
+
def get_auth_token_x509(
|
|
161
|
+
account: "InternalAccount",
|
|
162
|
+
dn: str,
|
|
163
|
+
appid: str,
|
|
164
|
+
ip: Optional[str] = None,
|
|
165
|
+
*,
|
|
166
|
+
session: "Session"
|
|
167
|
+
) -> Optional["TokenDict"]:
|
|
154
168
|
"""
|
|
155
169
|
Authenticate a Rucio account temporarily via an x509 certificate.
|
|
156
170
|
|
|
@@ -182,7 +196,14 @@ def get_auth_token_x509(account, dn, appid, ip=None, *, session: "Session"):
|
|
|
182
196
|
|
|
183
197
|
|
|
184
198
|
@transactional_session
|
|
185
|
-
def get_auth_token_gss(
|
|
199
|
+
def get_auth_token_gss(
|
|
200
|
+
account: "InternalAccount",
|
|
201
|
+
gsstoken: str,
|
|
202
|
+
appid: str,
|
|
203
|
+
ip: Optional[str] = None,
|
|
204
|
+
*,
|
|
205
|
+
session: "Session"
|
|
206
|
+
) -> Optional["TokenDict"]:
|
|
186
207
|
"""
|
|
187
208
|
Authenticate a Rucio account temporarily via a GSS token.
|
|
188
209
|
|
|
@@ -214,22 +235,34 @@ def get_auth_token_gss(account, gsstoken, appid, ip=None, *, session: "Session")
|
|
|
214
235
|
|
|
215
236
|
|
|
216
237
|
@transactional_session
|
|
217
|
-
def get_auth_token_ssh(
|
|
238
|
+
def get_auth_token_ssh(
|
|
239
|
+
account: "InternalAccount",
|
|
240
|
+
signature: str,
|
|
241
|
+
appid: str,
|
|
242
|
+
ip: Optional[str] = None,
|
|
243
|
+
*,
|
|
244
|
+
session: "Session"
|
|
245
|
+
) -> Optional["TokenDict"]:
|
|
218
246
|
"""
|
|
219
247
|
Authenticate a Rucio account temporarily via SSH key exchange.
|
|
220
248
|
|
|
221
249
|
The token lifetime is 1 hour.
|
|
222
250
|
|
|
223
251
|
:param account: Account identifier as a string.
|
|
224
|
-
:param signature: Response to server challenge signed with SSH private key as string.
|
|
252
|
+
:param signature: Response to server challenge signed with SSH private key as a base64 encoded string.
|
|
225
253
|
:param appid: The application identifier as a string.
|
|
226
254
|
:param ip: IP address of the client as a string.
|
|
227
255
|
:param session: The database session in use.
|
|
228
256
|
|
|
229
257
|
:returns: A dict with token and expires_at entries.
|
|
230
258
|
"""
|
|
231
|
-
|
|
232
|
-
|
|
259
|
+
|
|
260
|
+
# decode the signature which must come in base64 encoded
|
|
261
|
+
try:
|
|
262
|
+
signature += '=' * ((4 - len(signature) % 4) % 4) # adding required padding
|
|
263
|
+
decoded_signature = b64decode(signature)
|
|
264
|
+
except TypeError:
|
|
265
|
+
raise CannotAuthenticate(f'Cannot authenticate to account {account} with malformed signature')
|
|
233
266
|
|
|
234
267
|
# Make sure the account exists
|
|
235
268
|
if not account_exists(account, session=session):
|
|
@@ -266,7 +299,7 @@ def get_auth_token_ssh(account, signature, appid, ip=None, *, session: "Session"
|
|
|
266
299
|
pub_k = paramiko.RSAKey(data=b64decode(data))
|
|
267
300
|
for challenge_token in active_challenge_tokens:
|
|
268
301
|
if pub_k.verify_ssh_sig(str(challenge_token['token']).encode(),
|
|
269
|
-
paramiko.Message(
|
|
302
|
+
paramiko.Message(decoded_signature)):
|
|
270
303
|
match = True
|
|
271
304
|
break
|
|
272
305
|
if match:
|
|
@@ -288,7 +321,13 @@ def get_auth_token_ssh(account, signature, appid, ip=None, *, session: "Session"
|
|
|
288
321
|
|
|
289
322
|
|
|
290
323
|
@transactional_session
|
|
291
|
-
def get_ssh_challenge_token(
|
|
324
|
+
def get_ssh_challenge_token(
|
|
325
|
+
account: "InternalAccount",
|
|
326
|
+
appid: str,
|
|
327
|
+
ip: Optional[str] = None,
|
|
328
|
+
*,
|
|
329
|
+
session: "Session"
|
|
330
|
+
) -> Optional["TokenDict"]:
|
|
292
331
|
"""
|
|
293
332
|
Prepare a challenge token for subsequent SSH public key authentication.
|
|
294
333
|
|
|
@@ -324,7 +363,14 @@ def get_ssh_challenge_token(account, appid, ip=None, *, session: "Session"):
|
|
|
324
363
|
|
|
325
364
|
|
|
326
365
|
@transactional_session
|
|
327
|
-
def get_auth_token_saml(
|
|
366
|
+
def get_auth_token_saml(
|
|
367
|
+
account: "InternalAccount",
|
|
368
|
+
saml_nameid: str,
|
|
369
|
+
appid: str,
|
|
370
|
+
ip: Optional[str] = None,
|
|
371
|
+
*,
|
|
372
|
+
session: "Session"
|
|
373
|
+
) -> Optional["TokenDict"]:
|
|
328
374
|
"""
|
|
329
375
|
Authenticate a Rucio account temporarily via SAML.
|
|
330
376
|
|
|
@@ -355,7 +401,12 @@ def get_auth_token_saml(account, saml_nameid, appid, ip=None, *, session: "Sessi
|
|
|
355
401
|
|
|
356
402
|
|
|
357
403
|
@transactional_session
|
|
358
|
-
def redirect_auth_oidc(
|
|
404
|
+
def redirect_auth_oidc(
|
|
405
|
+
auth_code: str,
|
|
406
|
+
fetchtoken: bool = False,
|
|
407
|
+
*,
|
|
408
|
+
session: "Session"
|
|
409
|
+
) -> Optional[str]:
|
|
359
410
|
"""
|
|
360
411
|
Finds the Authentication URL in the Rucio DB oauth_requests table
|
|
361
412
|
and redirects user's browser to this URL.
|
|
@@ -396,7 +447,13 @@ def redirect_auth_oidc(auth_code, fetchtoken=False, *, session: "Session"):
|
|
|
396
447
|
|
|
397
448
|
|
|
398
449
|
@transactional_session
|
|
399
|
-
def delete_expired_tokens(
|
|
450
|
+
def delete_expired_tokens(
|
|
451
|
+
total_workers: int,
|
|
452
|
+
worker_number: int,
|
|
453
|
+
limit: int = 1000,
|
|
454
|
+
*,
|
|
455
|
+
session: "Session"
|
|
456
|
+
) -> int:
|
|
400
457
|
"""
|
|
401
458
|
Delete expired tokens.
|
|
402
459
|
|
|
@@ -456,7 +513,7 @@ def delete_expired_tokens(total_workers, worker_number, limit=1000, *, session:
|
|
|
456
513
|
|
|
457
514
|
|
|
458
515
|
@read_session
|
|
459
|
-
def query_token(token, *, session: "Session"):
|
|
516
|
+
def query_token(token: str, *, session: "Session") -> Optional["TokenValidationDict"]:
|
|
460
517
|
"""
|
|
461
518
|
Validate an authentication token using the database. This method will only be called
|
|
462
519
|
if no entry could be found in the according cache.
|
|
@@ -484,12 +541,12 @@ def query_token(token, *, session: "Session"):
|
|
|
484
541
|
)
|
|
485
542
|
result = session.execute(query).first()
|
|
486
543
|
if result:
|
|
487
|
-
return result._asdict()
|
|
544
|
+
return cast("TokenValidationDict", result._asdict())
|
|
488
545
|
return None
|
|
489
546
|
|
|
490
547
|
|
|
491
548
|
@transactional_session
|
|
492
|
-
def validate_auth_token(token: str, *, session: "Session") -> "
|
|
549
|
+
def validate_auth_token(token: str, *, session: "Session") -> "TokenValidationDict":
|
|
493
550
|
"""
|
|
494
551
|
Validate an authentication token.
|
|
495
552
|
|
|
@@ -510,12 +567,12 @@ def validate_auth_token(token: str, *, session: "Session") -> "dict[str, Any]":
|
|
|
510
567
|
token = token.strip()
|
|
511
568
|
cache_key = token.replace(' ', '')
|
|
512
569
|
|
|
513
|
-
# Check if token
|
|
514
|
-
value:
|
|
570
|
+
# Check if token can be found in cache region
|
|
571
|
+
value: Union[NoValue, "TokenValidationDict"] = TOKENREGION.get(cache_key)
|
|
515
572
|
if value is NO_VALUE: # no cached entry found
|
|
516
573
|
value = query_token(token, session=session)
|
|
517
574
|
if not value:
|
|
518
|
-
# identify JWT access token and
|
|
575
|
+
# identify JWT access token and validate
|
|
519
576
|
# & save it in Rucio if scope and audience are correct
|
|
520
577
|
if len(token.split(".")) == 3:
|
|
521
578
|
value = validate_jwt(token, session=session)
|
|
@@ -523,19 +580,19 @@ def validate_auth_token(token: str, *, session: "Session") -> "dict[str, Any]":
|
|
|
523
580
|
raise CannotAuthenticate(traceback.format_exc())
|
|
524
581
|
# save token in the cache
|
|
525
582
|
TOKENREGION.set(cache_key, value)
|
|
526
|
-
lifetime = value.get('lifetime', datetime.datetime(1970, 1, 1))
|
|
583
|
+
lifetime = value.get('lifetime', datetime.datetime(1970, 1, 1)) # type: ignore (value is narrowed to dict, but type-checker doesn't see it)
|
|
527
584
|
if lifetime < datetime.datetime.utcnow(): # check if expired
|
|
528
585
|
TOKENREGION.delete(cache_key)
|
|
529
586
|
raise CannotAuthenticate(f"Token found but expired since {date_to_str(lifetime)}.")
|
|
530
|
-
return value
|
|
587
|
+
return cast("TokenValidationDict", value)
|
|
531
588
|
|
|
532
589
|
|
|
533
|
-
def token_dictionary(token: models.Token):
|
|
590
|
+
def token_dictionary(token: models.Token) -> "TokenDict":
|
|
534
591
|
return {'token': token.token, 'expires_at': token.expired_at}
|
|
535
592
|
|
|
536
593
|
|
|
537
594
|
@transactional_session
|
|
538
|
-
def __delete_expired_tokens_account(account, *, session: "Session"):
|
|
595
|
+
def __delete_expired_tokens_account(account: "InternalAccount", *, session: "Session") -> None:
|
|
539
596
|
""""
|
|
540
597
|
Deletes expired tokens from the database.
|
|
541
598
|
|