rucio 37.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/__init__.py +17 -0
- rucio/alembicrevision.py +15 -0
- rucio/cli/__init__.py +14 -0
- rucio/cli/account.py +216 -0
- rucio/cli/bin_legacy/__init__.py +13 -0
- rucio/cli/bin_legacy/rucio.py +2825 -0
- rucio/cli/bin_legacy/rucio_admin.py +2500 -0
- rucio/cli/command.py +272 -0
- rucio/cli/config.py +72 -0
- rucio/cli/did.py +191 -0
- rucio/cli/download.py +128 -0
- rucio/cli/lifetime_exception.py +33 -0
- rucio/cli/replica.py +162 -0
- rucio/cli/rse.py +293 -0
- rucio/cli/rule.py +158 -0
- rucio/cli/scope.py +40 -0
- rucio/cli/subscription.py +73 -0
- rucio/cli/upload.py +60 -0
- rucio/cli/utils.py +226 -0
- rucio/client/__init__.py +15 -0
- rucio/client/accountclient.py +432 -0
- rucio/client/accountlimitclient.py +183 -0
- rucio/client/baseclient.py +983 -0
- rucio/client/client.py +120 -0
- rucio/client/configclient.py +126 -0
- rucio/client/credentialclient.py +59 -0
- rucio/client/didclient.py +868 -0
- rucio/client/diracclient.py +56 -0
- rucio/client/downloadclient.py +1783 -0
- rucio/client/exportclient.py +44 -0
- rucio/client/fileclient.py +50 -0
- rucio/client/importclient.py +42 -0
- rucio/client/lifetimeclient.py +90 -0
- rucio/client/lockclient.py +109 -0
- rucio/client/metaconventionsclient.py +140 -0
- rucio/client/pingclient.py +44 -0
- rucio/client/replicaclient.py +452 -0
- rucio/client/requestclient.py +125 -0
- rucio/client/richclient.py +317 -0
- rucio/client/rseclient.py +746 -0
- rucio/client/ruleclient.py +294 -0
- rucio/client/scopeclient.py +90 -0
- rucio/client/subscriptionclient.py +173 -0
- rucio/client/touchclient.py +82 -0
- rucio/client/uploadclient.py +969 -0
- rucio/common/__init__.py +13 -0
- rucio/common/bittorrent.py +234 -0
- rucio/common/cache.py +111 -0
- rucio/common/checksum.py +168 -0
- rucio/common/client.py +122 -0
- rucio/common/config.py +788 -0
- rucio/common/constants.py +217 -0
- rucio/common/constraints.py +17 -0
- rucio/common/didtype.py +237 -0
- rucio/common/dumper/__init__.py +342 -0
- rucio/common/dumper/consistency.py +497 -0
- rucio/common/dumper/data_models.py +362 -0
- rucio/common/dumper/path_parsing.py +75 -0
- rucio/common/exception.py +1208 -0
- rucio/common/extra.py +31 -0
- rucio/common/logging.py +420 -0
- rucio/common/pcache.py +1409 -0
- rucio/common/plugins.py +185 -0
- rucio/common/policy.py +93 -0
- rucio/common/schema/__init__.py +200 -0
- rucio/common/schema/generic.py +416 -0
- rucio/common/schema/generic_multi_vo.py +395 -0
- rucio/common/stomp_utils.py +423 -0
- rucio/common/stopwatch.py +55 -0
- rucio/common/test_rucio_server.py +154 -0
- rucio/common/types.py +483 -0
- rucio/common/utils.py +1688 -0
- rucio/core/__init__.py +13 -0
- rucio/core/account.py +496 -0
- rucio/core/account_counter.py +236 -0
- rucio/core/account_limit.py +425 -0
- rucio/core/authentication.py +620 -0
- rucio/core/config.py +437 -0
- rucio/core/credential.py +224 -0
- rucio/core/did.py +3004 -0
- rucio/core/did_meta_plugins/__init__.py +252 -0
- rucio/core/did_meta_plugins/did_column_meta.py +331 -0
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +165 -0
- rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
- rucio/core/did_meta_plugins/filter_engine.py +672 -0
- rucio/core/did_meta_plugins/json_meta.py +240 -0
- rucio/core/did_meta_plugins/mongo_meta.py +229 -0
- rucio/core/did_meta_plugins/postgres_meta.py +352 -0
- rucio/core/dirac.py +237 -0
- rucio/core/distance.py +187 -0
- rucio/core/exporter.py +59 -0
- rucio/core/heartbeat.py +363 -0
- rucio/core/identity.py +301 -0
- rucio/core/importer.py +260 -0
- rucio/core/lifetime_exception.py +377 -0
- rucio/core/lock.py +577 -0
- rucio/core/message.py +288 -0
- rucio/core/meta_conventions.py +203 -0
- rucio/core/monitor.py +448 -0
- rucio/core/naming_convention.py +195 -0
- rucio/core/nongrid_trace.py +136 -0
- rucio/core/oidc.py +1463 -0
- rucio/core/permission/__init__.py +161 -0
- rucio/core/permission/generic.py +1124 -0
- rucio/core/permission/generic_multi_vo.py +1144 -0
- rucio/core/quarantined_replica.py +224 -0
- rucio/core/replica.py +4483 -0
- rucio/core/replica_sorter.py +362 -0
- rucio/core/request.py +3091 -0
- rucio/core/rse.py +2079 -0
- rucio/core/rse_counter.py +185 -0
- rucio/core/rse_expression_parser.py +459 -0
- rucio/core/rse_selector.py +304 -0
- rucio/core/rule.py +4484 -0
- rucio/core/rule_grouping.py +1620 -0
- rucio/core/scope.py +181 -0
- rucio/core/subscription.py +362 -0
- rucio/core/topology.py +490 -0
- rucio/core/trace.py +375 -0
- rucio/core/transfer.py +1531 -0
- rucio/core/vo.py +169 -0
- rucio/core/volatile_replica.py +151 -0
- rucio/daemons/__init__.py +13 -0
- rucio/daemons/abacus/__init__.py +13 -0
- rucio/daemons/abacus/account.py +116 -0
- rucio/daemons/abacus/collection_replica.py +124 -0
- rucio/daemons/abacus/rse.py +117 -0
- rucio/daemons/atropos/__init__.py +13 -0
- rucio/daemons/atropos/atropos.py +242 -0
- rucio/daemons/auditor/__init__.py +289 -0
- rucio/daemons/auditor/hdfs.py +97 -0
- rucio/daemons/auditor/srmdumps.py +355 -0
- rucio/daemons/automatix/__init__.py +13 -0
- rucio/daemons/automatix/automatix.py +304 -0
- rucio/daemons/badreplicas/__init__.py +13 -0
- rucio/daemons/badreplicas/minos.py +322 -0
- rucio/daemons/badreplicas/minos_temporary_expiration.py +171 -0
- rucio/daemons/badreplicas/necromancer.py +196 -0
- rucio/daemons/bb8/__init__.py +13 -0
- rucio/daemons/bb8/bb8.py +353 -0
- rucio/daemons/bb8/common.py +759 -0
- rucio/daemons/bb8/nuclei_background_rebalance.py +153 -0
- rucio/daemons/bb8/t2_background_rebalance.py +153 -0
- rucio/daemons/cache/__init__.py +13 -0
- rucio/daemons/cache/consumer.py +133 -0
- rucio/daemons/common.py +405 -0
- rucio/daemons/conveyor/__init__.py +13 -0
- rucio/daemons/conveyor/common.py +562 -0
- rucio/daemons/conveyor/finisher.py +529 -0
- rucio/daemons/conveyor/poller.py +394 -0
- rucio/daemons/conveyor/preparer.py +205 -0
- rucio/daemons/conveyor/receiver.py +179 -0
- rucio/daemons/conveyor/stager.py +133 -0
- rucio/daemons/conveyor/submitter.py +403 -0
- rucio/daemons/conveyor/throttler.py +532 -0
- rucio/daemons/follower/__init__.py +13 -0
- rucio/daemons/follower/follower.py +101 -0
- rucio/daemons/hermes/__init__.py +13 -0
- rucio/daemons/hermes/hermes.py +534 -0
- rucio/daemons/judge/__init__.py +13 -0
- rucio/daemons/judge/cleaner.py +159 -0
- rucio/daemons/judge/evaluator.py +185 -0
- rucio/daemons/judge/injector.py +162 -0
- rucio/daemons/judge/repairer.py +154 -0
- rucio/daemons/oauthmanager/__init__.py +13 -0
- rucio/daemons/oauthmanager/oauthmanager.py +198 -0
- rucio/daemons/reaper/__init__.py +13 -0
- rucio/daemons/reaper/dark_reaper.py +282 -0
- rucio/daemons/reaper/reaper.py +739 -0
- rucio/daemons/replicarecoverer/__init__.py +13 -0
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +626 -0
- rucio/daemons/rsedecommissioner/__init__.py +13 -0
- rucio/daemons/rsedecommissioner/config.py +81 -0
- rucio/daemons/rsedecommissioner/profiles/__init__.py +24 -0
- rucio/daemons/rsedecommissioner/profiles/atlas.py +60 -0
- rucio/daemons/rsedecommissioner/profiles/generic.py +452 -0
- rucio/daemons/rsedecommissioner/profiles/types.py +93 -0
- rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
- rucio/daemons/storage/__init__.py +13 -0
- rucio/daemons/storage/consistency/__init__.py +13 -0
- rucio/daemons/storage/consistency/actions.py +848 -0
- rucio/daemons/tracer/__init__.py +13 -0
- rucio/daemons/tracer/kronos.py +511 -0
- rucio/daemons/transmogrifier/__init__.py +13 -0
- rucio/daemons/transmogrifier/transmogrifier.py +762 -0
- rucio/daemons/undertaker/__init__.py +13 -0
- rucio/daemons/undertaker/undertaker.py +137 -0
- rucio/db/__init__.py +13 -0
- rucio/db/sqla/__init__.py +52 -0
- rucio/db/sqla/constants.py +206 -0
- rucio/db/sqla/migrate_repo/__init__.py +13 -0
- rucio/db/sqla/migrate_repo/env.py +110 -0
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +70 -0
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +91 -0
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +76 -0
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +43 -0
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +50 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +68 -0
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +40 -0
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +45 -0
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +60 -0
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +40 -0
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +140 -0
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +73 -0
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +74 -0
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +43 -0
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +50 -0
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +134 -0
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +64 -0
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +39 -0
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +64 -0
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +51 -0
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +41 -0
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +43 -0
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +44 -0
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +53 -0
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +38 -0
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +47 -0
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +57 -0
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +69 -0
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +42 -0
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +46 -0
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +40 -0
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +67 -0
- rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +44 -0
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +77 -0
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +60 -0
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +72 -0
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +42 -0
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +65 -0
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +133 -0
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +76 -0
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +60 -0
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +44 -0
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +64 -0
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +40 -0
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +43 -0
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +44 -0
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +78 -0
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +41 -0
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +44 -0
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +49 -0
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +40 -0
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +63 -0
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +55 -0
- rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +45 -0
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +47 -0
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +58 -0
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +45 -0
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +106 -0
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +55 -0
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +50 -0
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +43 -0
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +41 -0
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +91 -0
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +72 -0
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +49 -0
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +43 -0
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +53 -0
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +45 -0
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +68 -0
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +45 -0
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +94 -0
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +54 -0
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +72 -0
- rucio/db/sqla/migrate_repo/versions/a08fa8de1545_transfer_stats_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +76 -0
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +47 -0
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +121 -0
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +59 -0
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +52 -0
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +54 -0
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +64 -0
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +49 -0
- rucio/db/sqla/migrate_repo/versions/b0070f3695c8_add_deletedidmeta_table.py +57 -0
- rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +43 -0
- rucio/db/sqla/migrate_repo/versions/b5493606bbf5_fix_primary_key_for_subscription_history.py +41 -0
- rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +91 -0
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +40 -0
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +143 -0
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +76 -0
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +50 -0
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +72 -0
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +43 -0
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +65 -0
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +47 -0
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +146 -0
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +104 -0
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +44 -0
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +43 -0
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +103 -0
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +49 -0
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +104 -0
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +29 -0
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +74 -0
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +43 -0
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +37 -0
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +43 -0
- rucio/db/sqla/models.py +1743 -0
- rucio/db/sqla/sautils.py +55 -0
- rucio/db/sqla/session.py +529 -0
- rucio/db/sqla/types.py +206 -0
- rucio/db/sqla/util.py +543 -0
- rucio/gateway/__init__.py +13 -0
- rucio/gateway/account.py +345 -0
- rucio/gateway/account_limit.py +363 -0
- rucio/gateway/authentication.py +381 -0
- rucio/gateway/config.py +227 -0
- rucio/gateway/credential.py +70 -0
- rucio/gateway/did.py +987 -0
- rucio/gateway/dirac.py +83 -0
- rucio/gateway/exporter.py +60 -0
- rucio/gateway/heartbeat.py +76 -0
- rucio/gateway/identity.py +189 -0
- rucio/gateway/importer.py +46 -0
- rucio/gateway/lifetime_exception.py +121 -0
- rucio/gateway/lock.py +153 -0
- rucio/gateway/meta_conventions.py +98 -0
- rucio/gateway/permission.py +74 -0
- rucio/gateway/quarantined_replica.py +79 -0
- rucio/gateway/replica.py +538 -0
- rucio/gateway/request.py +330 -0
- rucio/gateway/rse.py +632 -0
- rucio/gateway/rule.py +437 -0
- rucio/gateway/scope.py +100 -0
- rucio/gateway/subscription.py +280 -0
- rucio/gateway/vo.py +126 -0
- rucio/rse/__init__.py +96 -0
- rucio/rse/protocols/__init__.py +13 -0
- rucio/rse/protocols/bittorrent.py +194 -0
- rucio/rse/protocols/cache.py +111 -0
- rucio/rse/protocols/dummy.py +100 -0
- rucio/rse/protocols/gfal.py +708 -0
- rucio/rse/protocols/globus.py +243 -0
- rucio/rse/protocols/http_cache.py +82 -0
- rucio/rse/protocols/mock.py +123 -0
- rucio/rse/protocols/ngarc.py +209 -0
- rucio/rse/protocols/posix.py +250 -0
- rucio/rse/protocols/protocol.py +361 -0
- rucio/rse/protocols/rclone.py +365 -0
- rucio/rse/protocols/rfio.py +145 -0
- rucio/rse/protocols/srm.py +338 -0
- rucio/rse/protocols/ssh.py +414 -0
- rucio/rse/protocols/storm.py +195 -0
- rucio/rse/protocols/webdav.py +594 -0
- rucio/rse/protocols/xrootd.py +302 -0
- rucio/rse/rsemanager.py +881 -0
- rucio/rse/translation.py +260 -0
- rucio/tests/__init__.py +13 -0
- rucio/tests/common.py +280 -0
- rucio/tests/common_server.py +149 -0
- rucio/transfertool/__init__.py +13 -0
- rucio/transfertool/bittorrent.py +200 -0
- rucio/transfertool/bittorrent_driver.py +50 -0
- rucio/transfertool/bittorrent_driver_qbittorrent.py +134 -0
- rucio/transfertool/fts3.py +1600 -0
- rucio/transfertool/fts3_plugins.py +152 -0
- rucio/transfertool/globus.py +201 -0
- rucio/transfertool/globus_library.py +181 -0
- rucio/transfertool/mock.py +89 -0
- rucio/transfertool/transfertool.py +221 -0
- rucio/vcsversion.py +11 -0
- rucio/version.py +45 -0
- rucio/web/__init__.py +13 -0
- rucio/web/rest/__init__.py +13 -0
- rucio/web/rest/flaskapi/__init__.py +13 -0
- rucio/web/rest/flaskapi/authenticated_bp.py +27 -0
- rucio/web/rest/flaskapi/v1/__init__.py +13 -0
- rucio/web/rest/flaskapi/v1/accountlimits.py +236 -0
- rucio/web/rest/flaskapi/v1/accounts.py +1103 -0
- rucio/web/rest/flaskapi/v1/archives.py +102 -0
- rucio/web/rest/flaskapi/v1/auth.py +1644 -0
- rucio/web/rest/flaskapi/v1/common.py +426 -0
- rucio/web/rest/flaskapi/v1/config.py +304 -0
- rucio/web/rest/flaskapi/v1/credentials.py +213 -0
- rucio/web/rest/flaskapi/v1/dids.py +2340 -0
- rucio/web/rest/flaskapi/v1/dirac.py +116 -0
- rucio/web/rest/flaskapi/v1/export.py +75 -0
- rucio/web/rest/flaskapi/v1/heartbeats.py +127 -0
- rucio/web/rest/flaskapi/v1/identities.py +285 -0
- rucio/web/rest/flaskapi/v1/import.py +132 -0
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +312 -0
- rucio/web/rest/flaskapi/v1/locks.py +358 -0
- rucio/web/rest/flaskapi/v1/main.py +91 -0
- rucio/web/rest/flaskapi/v1/meta_conventions.py +241 -0
- rucio/web/rest/flaskapi/v1/metrics.py +36 -0
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
- rucio/web/rest/flaskapi/v1/ping.py +88 -0
- rucio/web/rest/flaskapi/v1/redirect.py +366 -0
- rucio/web/rest/flaskapi/v1/replicas.py +1894 -0
- rucio/web/rest/flaskapi/v1/requests.py +998 -0
- rucio/web/rest/flaskapi/v1/rses.py +2250 -0
- rucio/web/rest/flaskapi/v1/rules.py +854 -0
- rucio/web/rest/flaskapi/v1/scopes.py +159 -0
- rucio/web/rest/flaskapi/v1/subscriptions.py +650 -0
- rucio/web/rest/flaskapi/v1/templates/auth_crash.html +80 -0
- rucio/web/rest/flaskapi/v1/templates/auth_granted.html +82 -0
- rucio/web/rest/flaskapi/v1/traces.py +137 -0
- rucio/web/rest/flaskapi/v1/types.py +20 -0
- rucio/web/rest/flaskapi/v1/vos.py +278 -0
- rucio/web/rest/main.py +18 -0
- rucio/web/rest/metrics.py +27 -0
- rucio/web/rest/ping.py +27 -0
- rucio-37.0.0rc1.data/data/rucio/etc/alembic.ini.template +71 -0
- rucio-37.0.0rc1.data/data/rucio/etc/alembic_offline.ini.template +74 -0
- rucio-37.0.0rc1.data/data/rucio/etc/globus-config.yml.template +5 -0
- rucio-37.0.0rc1.data/data/rucio/etc/ldap.cfg.template +30 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.atlas.client.template +43 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.template +241 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio_multi_vo.cfg.template +217 -0
- rucio-37.0.0rc1.data/data/rucio/requirements.server.txt +297 -0
- rucio-37.0.0rc1.data/data/rucio/tools/bootstrap.py +34 -0
- rucio-37.0.0rc1.data/data/rucio/tools/merge_rucio_configs.py +144 -0
- rucio-37.0.0rc1.data/data/rucio/tools/reset_database.py +40 -0
- rucio-37.0.0rc1.data/scripts/rucio +133 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-account +74 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-collection-replica +46 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-rse +78 -0
- rucio-37.0.0rc1.data/scripts/rucio-admin +97 -0
- rucio-37.0.0rc1.data/scripts/rucio-atropos +60 -0
- rucio-37.0.0rc1.data/scripts/rucio-auditor +206 -0
- rucio-37.0.0rc1.data/scripts/rucio-automatix +50 -0
- rucio-37.0.0rc1.data/scripts/rucio-bb8 +57 -0
- rucio-37.0.0rc1.data/scripts/rucio-cache-client +141 -0
- rucio-37.0.0rc1.data/scripts/rucio-cache-consumer +42 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-finisher +58 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-poller +66 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-preparer +37 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-receiver +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-stager +76 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-submitter +139 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-throttler +104 -0
- rucio-37.0.0rc1.data/scripts/rucio-dark-reaper +53 -0
- rucio-37.0.0rc1.data/scripts/rucio-dumper +160 -0
- rucio-37.0.0rc1.data/scripts/rucio-follower +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-hermes +54 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-cleaner +89 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-evaluator +137 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-injector +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-repairer +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-kronos +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-minos +53 -0
- rucio-37.0.0rc1.data/scripts/rucio-minos-temporary-expiration +50 -0
- rucio-37.0.0rc1.data/scripts/rucio-necromancer +120 -0
- rucio-37.0.0rc1.data/scripts/rucio-oauth-manager +63 -0
- rucio-37.0.0rc1.data/scripts/rucio-reaper +83 -0
- rucio-37.0.0rc1.data/scripts/rucio-replica-recoverer +248 -0
- rucio-37.0.0rc1.data/scripts/rucio-rse-decommissioner +66 -0
- rucio-37.0.0rc1.data/scripts/rucio-storage-consistency-actions +74 -0
- rucio-37.0.0rc1.data/scripts/rucio-transmogrifier +77 -0
- rucio-37.0.0rc1.data/scripts/rucio-undertaker +76 -0
- rucio-37.0.0rc1.dist-info/METADATA +92 -0
- rucio-37.0.0rc1.dist-info/RECORD +487 -0
- rucio-37.0.0rc1.dist-info/WHEEL +5 -0
- rucio-37.0.0rc1.dist-info/licenses/AUTHORS.rst +100 -0
- rucio-37.0.0rc1.dist-info/licenses/LICENSE +201 -0
- rucio-37.0.0rc1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
import datetime
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
from sqlalchemy import and_, delete, insert, literal, select
|
|
18
|
+
from sqlalchemy.exc import NoResultFound
|
|
19
|
+
|
|
20
|
+
from rucio.db.sqla import filter_thread_work, models
|
|
21
|
+
from rucio.db.sqla.session import read_session, transactional_session
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from sqlalchemy.orm import Session
|
|
25
|
+
|
|
26
|
+
from rucio.common.types import InternalAccount, RSEAccountCounterDict
|
|
27
|
+
|
|
28
|
+
MAX_COUNTERS = 10
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@transactional_session
|
|
32
|
+
def add_counter(
|
|
33
|
+
rse_id: str,
|
|
34
|
+
account: "InternalAccount",
|
|
35
|
+
*,
|
|
36
|
+
session: "Session"
|
|
37
|
+
) -> None:
|
|
38
|
+
"""
|
|
39
|
+
Creates the specified counter for a rse_id and account.
|
|
40
|
+
|
|
41
|
+
:param rse_id: The id of the RSE.
|
|
42
|
+
:param account: The account name.
|
|
43
|
+
:param session: The database session in use
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
models.AccountUsage(rse_id=rse_id, account=account, files=0, bytes=0).save(session=session)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@transactional_session
|
|
50
|
+
def increase(
|
|
51
|
+
rse_id: str,
|
|
52
|
+
account: "InternalAccount",
|
|
53
|
+
files: int,
|
|
54
|
+
bytes_: int,
|
|
55
|
+
*,
|
|
56
|
+
session: "Session"
|
|
57
|
+
) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Increments the specified counter by the specified amount.
|
|
60
|
+
|
|
61
|
+
:param rse_id: The id of the RSE.
|
|
62
|
+
:param account: The account name.
|
|
63
|
+
:param files: The number of added/removed files.
|
|
64
|
+
:param bytes_: The corresponding amount in bytes.
|
|
65
|
+
:param session: The database session in use.
|
|
66
|
+
"""
|
|
67
|
+
models.UpdatedAccountCounter(account=account, rse_id=rse_id, files=files, bytes=bytes_).save(session=session)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@transactional_session
|
|
71
|
+
def decrease(
|
|
72
|
+
rse_id: str,
|
|
73
|
+
account: "InternalAccount",
|
|
74
|
+
files: int,
|
|
75
|
+
bytes_: int,
|
|
76
|
+
*,
|
|
77
|
+
session: "Session"
|
|
78
|
+
) -> None:
|
|
79
|
+
"""
|
|
80
|
+
Decreases the specified counter by the specified amount.
|
|
81
|
+
|
|
82
|
+
:param rse_id: The id of the RSE.
|
|
83
|
+
:param account: The account name.
|
|
84
|
+
:param files: The amount of files.
|
|
85
|
+
:param bytes_: The amount of bytes.
|
|
86
|
+
:param session: The database session in use.
|
|
87
|
+
"""
|
|
88
|
+
return increase(rse_id=rse_id, account=account, files=-files, bytes_=-bytes_, session=session)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@transactional_session
|
|
92
|
+
def del_counter(
|
|
93
|
+
rse_id: str,
|
|
94
|
+
account: "InternalAccount",
|
|
95
|
+
*,
|
|
96
|
+
session: "Session"
|
|
97
|
+
) -> None:
|
|
98
|
+
"""
|
|
99
|
+
Resets the specified counter and initializes it by the specified amounts.
|
|
100
|
+
|
|
101
|
+
:param rse_id: The id of the RSE.
|
|
102
|
+
:param account: The account name.
|
|
103
|
+
:param session: The database session in use.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
stmt = delete(
|
|
107
|
+
models.AccountUsage
|
|
108
|
+
).where(
|
|
109
|
+
and_(models.AccountUsage.rse_id == rse_id,
|
|
110
|
+
models.AccountUsage.account == account)
|
|
111
|
+
).execution_options(
|
|
112
|
+
synchronize_session=False
|
|
113
|
+
)
|
|
114
|
+
session.execute(stmt)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@read_session
|
|
118
|
+
def get_updated_account_counters(
|
|
119
|
+
total_workers: int,
|
|
120
|
+
worker_number: int,
|
|
121
|
+
*,
|
|
122
|
+
session: "Session"
|
|
123
|
+
) -> list["RSEAccountCounterDict"]:
|
|
124
|
+
"""
|
|
125
|
+
Get updated rse_counters.
|
|
126
|
+
|
|
127
|
+
:param total_workers: Number of total workers.
|
|
128
|
+
:param worker_number: id of the executing worker.
|
|
129
|
+
:param session: Database session in use.
|
|
130
|
+
:returns: List of rse_ids whose rse_counters need to be updated.
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
query = select(
|
|
134
|
+
models.UpdatedAccountCounter.account,
|
|
135
|
+
models.UpdatedAccountCounter.rse_id,
|
|
136
|
+
).distinct(
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
query = filter_thread_work(session=session, query=query, total_threads=total_workers, thread_id=worker_number, hash_variable='CONCAT(account, rse_id)')
|
|
140
|
+
|
|
141
|
+
return [row._asdict() for row in session.execute(query).all()] # type: ignore (pending SQLA2.1: https://github.com/rucio/rucio/discussions/6615)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@transactional_session
|
|
145
|
+
def update_account_counter(
|
|
146
|
+
account: "InternalAccount",
|
|
147
|
+
rse_id: str,
|
|
148
|
+
*,
|
|
149
|
+
session: "Session"
|
|
150
|
+
) -> None:
|
|
151
|
+
"""
|
|
152
|
+
Read the updated_account_counters and update the account_counter.
|
|
153
|
+
|
|
154
|
+
:param account: The account to update.
|
|
155
|
+
:param rse_id: The rse_id to update.
|
|
156
|
+
:param session: Database session in use.
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
stmt = select(
|
|
160
|
+
models.UpdatedAccountCounter
|
|
161
|
+
).where(
|
|
162
|
+
and_(models.UpdatedAccountCounter.account == account,
|
|
163
|
+
models.UpdatedAccountCounter.rse_id == rse_id)
|
|
164
|
+
)
|
|
165
|
+
updated_account_counters = session.execute(stmt).scalars().all()
|
|
166
|
+
|
|
167
|
+
try:
|
|
168
|
+
stmt = select(
|
|
169
|
+
models.AccountUsage
|
|
170
|
+
).where(
|
|
171
|
+
and_(models.AccountUsage.account == account,
|
|
172
|
+
models.AccountUsage.rse_id == rse_id)
|
|
173
|
+
)
|
|
174
|
+
account_counter = session.execute(stmt).scalar_one()
|
|
175
|
+
account_counter.bytes += sum([updated_account_counter.bytes for updated_account_counter in updated_account_counters])
|
|
176
|
+
account_counter.files += sum([updated_account_counter.files for updated_account_counter in updated_account_counters])
|
|
177
|
+
except NoResultFound:
|
|
178
|
+
models.AccountUsage(rse_id=rse_id,
|
|
179
|
+
account=account,
|
|
180
|
+
files=sum([updated_account_counter.files for updated_account_counter in updated_account_counters]),
|
|
181
|
+
bytes=sum([updated_account_counter.bytes for updated_account_counter in updated_account_counters])).save(session=session)
|
|
182
|
+
|
|
183
|
+
for update in updated_account_counters:
|
|
184
|
+
update.delete(flush=False, session=session)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@transactional_session
|
|
188
|
+
def update_account_counter_history(
|
|
189
|
+
account: "InternalAccount",
|
|
190
|
+
rse_id: str,
|
|
191
|
+
*,
|
|
192
|
+
session: "Session"
|
|
193
|
+
) -> None:
|
|
194
|
+
"""
|
|
195
|
+
Read the AccountUsage and update the AccountUsageHistory.
|
|
196
|
+
|
|
197
|
+
:param account: The account to update.
|
|
198
|
+
:param rse_id: The rse_id to update.
|
|
199
|
+
:param session: Database session in use.
|
|
200
|
+
"""
|
|
201
|
+
stmt = select(
|
|
202
|
+
models.AccountUsage
|
|
203
|
+
).where(
|
|
204
|
+
and_(models.AccountUsage.account == account,
|
|
205
|
+
models.AccountUsage.rse_id == rse_id)
|
|
206
|
+
)
|
|
207
|
+
counter = session.execute(stmt).scalar_one_or_none()
|
|
208
|
+
if counter:
|
|
209
|
+
models.AccountUsageHistory(rse_id=rse_id, account=account, files=counter.files, bytes=counter.bytes).save(session=session)
|
|
210
|
+
else:
|
|
211
|
+
models.AccountUsageHistory(rse_id=rse_id, account=account, files=0, bytes=0).save(session=session)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@transactional_session
|
|
215
|
+
def fill_account_counter_history_table(*, session: "Session") -> None:
|
|
216
|
+
"""
|
|
217
|
+
Make a snapshot of current counters
|
|
218
|
+
|
|
219
|
+
:param session: Database session in use.
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
select_counters_stmt = select(
|
|
223
|
+
models.AccountUsage.rse_id,
|
|
224
|
+
models.AccountUsage.account,
|
|
225
|
+
models.AccountUsage.files,
|
|
226
|
+
models.AccountUsage.bytes,
|
|
227
|
+
literal(datetime.datetime.utcnow()),
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
stmt = insert(
|
|
231
|
+
models.AccountUsageHistory
|
|
232
|
+
).from_select(
|
|
233
|
+
['rse_id', 'account', 'files', 'bytes', 'updated_at'],
|
|
234
|
+
select_counters_stmt
|
|
235
|
+
)
|
|
236
|
+
session.execute(stmt)
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from typing import TYPE_CHECKING, Optional, Union
|
|
16
|
+
|
|
17
|
+
from sqlalchemy.exc import NoResultFound
|
|
18
|
+
from sqlalchemy.sql import func, literal, select
|
|
19
|
+
from sqlalchemy.sql.expression import and_, or_
|
|
20
|
+
|
|
21
|
+
from rucio.core.account import get_all_rse_usages_per_account
|
|
22
|
+
from rucio.core.rse import get_rse_name
|
|
23
|
+
from rucio.core.rse_expression_parser import parse_expression
|
|
24
|
+
from rucio.db.sqla import models
|
|
25
|
+
from rucio.db.sqla.session import read_session, transactional_session
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from sqlalchemy.orm import Session
|
|
29
|
+
|
|
30
|
+
from rucio.common.types import InternalAccount, RSEAccountUsageDict, RSEGlobalAccountUsageDict, RSELocalAccountUsageDict, RSEResolvedGlobalAccountLimitDict
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@read_session
|
|
34
|
+
def get_rse_account_usage(rse_id: str, *, session: "Session") -> list["RSEAccountUsageDict"]:
|
|
35
|
+
"""
|
|
36
|
+
Returns the account limit and usage for all accounts on a RSE.
|
|
37
|
+
|
|
38
|
+
:param rse_id: The id of the RSE.
|
|
39
|
+
:param session: Database session in use.
|
|
40
|
+
:return: List of dictionaries.
|
|
41
|
+
"""
|
|
42
|
+
result = []
|
|
43
|
+
stmt = select(
|
|
44
|
+
models.RSE.id.label('rse_id'),
|
|
45
|
+
models.RSE.vo.label('rse_vo'),
|
|
46
|
+
models.RSE.rse.label('rse_name'),
|
|
47
|
+
models.Account.account,
|
|
48
|
+
models.AccountUsage.files.label('used_files'),
|
|
49
|
+
models.AccountUsage.bytes.label('used_bytes'),
|
|
50
|
+
models.AccountLimit.bytes.label('quota_bytes'),
|
|
51
|
+
).where(
|
|
52
|
+
models.RSE.id == rse_id
|
|
53
|
+
).join_from(
|
|
54
|
+
models.RSE,
|
|
55
|
+
models.Account,
|
|
56
|
+
or_(
|
|
57
|
+
and_(
|
|
58
|
+
models.RSE.vo == 'def',
|
|
59
|
+
models.Account.account.notlike('%@%')
|
|
60
|
+
),
|
|
61
|
+
and_(
|
|
62
|
+
models.RSE.vo != 'def',
|
|
63
|
+
models.Account.account.like(literal('%@') + models.RSE.vo)
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
).outerjoin(
|
|
67
|
+
models.AccountUsage,
|
|
68
|
+
and_(
|
|
69
|
+
models.AccountUsage.account == models.Account.account,
|
|
70
|
+
models.AccountUsage.rse_id == models.RSE.id
|
|
71
|
+
)
|
|
72
|
+
).outerjoin(
|
|
73
|
+
models.AccountLimit,
|
|
74
|
+
and_(
|
|
75
|
+
models.AccountLimit.account == models.Account.account,
|
|
76
|
+
models.AccountLimit.rse_id == models.RSE.id
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
for row in session.execute(stmt):
|
|
80
|
+
if row.rse_vo != row.account.vo:
|
|
81
|
+
continue
|
|
82
|
+
result.append({
|
|
83
|
+
'rse_id': row.rse_id,
|
|
84
|
+
'rse': row.rse_name,
|
|
85
|
+
'account': row.account,
|
|
86
|
+
'used_files': row.used_files if row.used_files is not None else 0,
|
|
87
|
+
'used_bytes': row.used_bytes if row.used_bytes is not None else 0,
|
|
88
|
+
'quota_bytes': row.quota_bytes
|
|
89
|
+
})
|
|
90
|
+
return result
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@read_session
|
|
94
|
+
def get_global_account_limits(account: Optional["InternalAccount"] = None, *, session: "Session") -> dict[str, "RSEResolvedGlobalAccountLimitDict"]:
|
|
95
|
+
"""
|
|
96
|
+
Returns the global account limits for the account.
|
|
97
|
+
|
|
98
|
+
:param account: Account to check the limit for.
|
|
99
|
+
:param session: Database session in use.
|
|
100
|
+
:return: Dict {'MOCK': {'resolved_rses': ['MOCK'], 'limit': 10, 'resolved_rse_ids': [123]}}.
|
|
101
|
+
"""
|
|
102
|
+
if account:
|
|
103
|
+
stmt = select(
|
|
104
|
+
models.AccountGlobalLimit
|
|
105
|
+
).where(
|
|
106
|
+
models.AccountGlobalLimit.account == account
|
|
107
|
+
)
|
|
108
|
+
global_account_limits = session.execute(stmt).scalars().all()
|
|
109
|
+
else:
|
|
110
|
+
stmt = select(
|
|
111
|
+
models.AccountGlobalLimit
|
|
112
|
+
)
|
|
113
|
+
global_account_limits = session.execute(stmt).scalars().all()
|
|
114
|
+
|
|
115
|
+
resolved_global_account_limits = {}
|
|
116
|
+
for limit in global_account_limits:
|
|
117
|
+
if account:
|
|
118
|
+
resolved_rses = parse_expression(limit['rse_expression'], filter_={'vo': account.vo}, session=session)
|
|
119
|
+
else:
|
|
120
|
+
resolved_rses = parse_expression(limit['rse_expression'], session=session)
|
|
121
|
+
limit_in_bytes = limit['bytes']
|
|
122
|
+
if limit_in_bytes == -1:
|
|
123
|
+
limit_in_bytes = float('inf')
|
|
124
|
+
resolved_global_account_limits[limit['rse_expression']] = {
|
|
125
|
+
'resolved_rses': [resolved_rse['rse'] for resolved_rse in resolved_rses],
|
|
126
|
+
'resolved_rse_ids': [resolved_rse['id'] for resolved_rse in resolved_rses],
|
|
127
|
+
'limit': limit_in_bytes
|
|
128
|
+
}
|
|
129
|
+
return resolved_global_account_limits
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@read_session
|
|
133
|
+
def get_global_account_limit(account: "InternalAccount", rse_expression: str, *, session: "Session") -> Union[int, float, None]:
|
|
134
|
+
"""
|
|
135
|
+
Returns the global account limit for the account on the rse expression.
|
|
136
|
+
|
|
137
|
+
:param account: Account to check the limit for.
|
|
138
|
+
:param rse_expression: RSE expression to check the limit for.
|
|
139
|
+
:param session: Database session in use.
|
|
140
|
+
:return: Limit in Bytes.
|
|
141
|
+
"""
|
|
142
|
+
try:
|
|
143
|
+
stmt = select(
|
|
144
|
+
models.AccountGlobalLimit
|
|
145
|
+
).where(
|
|
146
|
+
and_(models.AccountGlobalLimit.account == account,
|
|
147
|
+
models.AccountGlobalLimit.rse_expression == rse_expression)
|
|
148
|
+
)
|
|
149
|
+
global_account_limit = session.execute(stmt).scalar_one()
|
|
150
|
+
if global_account_limit.bytes == -1:
|
|
151
|
+
return float("inf")
|
|
152
|
+
else:
|
|
153
|
+
return global_account_limit.bytes
|
|
154
|
+
except NoResultFound:
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@read_session
|
|
159
|
+
def get_local_account_limit(account: "InternalAccount", rse_id: str, *, session: "Session") -> Union[int, float, None]:
|
|
160
|
+
"""
|
|
161
|
+
Returns the account limit for the account on the rse.
|
|
162
|
+
|
|
163
|
+
:param account: Account to check the limit for.
|
|
164
|
+
:param rse_id: RSE id to check the limit for.
|
|
165
|
+
:param session: Database session in use.
|
|
166
|
+
:return: Limit in Bytes.
|
|
167
|
+
"""
|
|
168
|
+
try:
|
|
169
|
+
stmt = select(
|
|
170
|
+
models.AccountLimit
|
|
171
|
+
).where(
|
|
172
|
+
and_(models.AccountLimit.account == account,
|
|
173
|
+
models.AccountLimit.rse_id == rse_id)
|
|
174
|
+
)
|
|
175
|
+
account_limit = session.execute(stmt).scalar_one()
|
|
176
|
+
if account_limit.bytes == -1:
|
|
177
|
+
return float("inf")
|
|
178
|
+
else:
|
|
179
|
+
return account_limit.bytes
|
|
180
|
+
except NoResultFound:
|
|
181
|
+
return None
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@read_session
|
|
185
|
+
def get_local_account_limits(account: "InternalAccount", rse_ids: Optional[list[str]] = None, *, session: "Session") -> dict[str, int]:
|
|
186
|
+
"""
|
|
187
|
+
Returns the account limits for the account on the list of rses.
|
|
188
|
+
|
|
189
|
+
:param account: Account to check the limit for.
|
|
190
|
+
:param rse_ids: List of RSE ids to check the limit for.
|
|
191
|
+
:param session: Database session in use.
|
|
192
|
+
:return: Dictionary {'rse_id': bytes, ...}.
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
account_limits = {}
|
|
196
|
+
if rse_ids:
|
|
197
|
+
rse_id_clauses = []
|
|
198
|
+
for rse_id in rse_ids:
|
|
199
|
+
rse_id_clauses.append(and_(models.AccountLimit.rse_id == rse_id,
|
|
200
|
+
models.AccountLimit.account == account))
|
|
201
|
+
rse_id_clause_chunks = [rse_id_clauses[x:x + 10] for x in range(0, len(rse_id_clauses), 10)]
|
|
202
|
+
for rse_id_chunk in rse_id_clause_chunks:
|
|
203
|
+
stmt = select(
|
|
204
|
+
models.AccountLimit
|
|
205
|
+
).where(
|
|
206
|
+
or_(*rse_id_chunk)
|
|
207
|
+
)
|
|
208
|
+
tmp_limits = session.execute(stmt).scalars().all()
|
|
209
|
+
for limit in tmp_limits:
|
|
210
|
+
if limit.bytes == -1:
|
|
211
|
+
account_limits[limit.rse_id] = float("inf")
|
|
212
|
+
else:
|
|
213
|
+
account_limits[limit.rse_id] = limit.bytes
|
|
214
|
+
else:
|
|
215
|
+
stmt = select(
|
|
216
|
+
models.AccountLimit
|
|
217
|
+
).where(
|
|
218
|
+
models.AccountLimit.account == account
|
|
219
|
+
)
|
|
220
|
+
account_limits_tmp = session.execute(stmt).scalars().all()
|
|
221
|
+
for limit in account_limits_tmp:
|
|
222
|
+
if limit.bytes == -1:
|
|
223
|
+
account_limits[limit.rse_id] = float("inf")
|
|
224
|
+
else:
|
|
225
|
+
account_limits[limit.rse_id] = limit.bytes
|
|
226
|
+
return account_limits
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@transactional_session
|
|
230
|
+
def set_local_account_limit(account: "InternalAccount", rse_id: str, bytes_: int, *, session: "Session") -> None:
|
|
231
|
+
"""
|
|
232
|
+
Returns the limits for the account on the rse.
|
|
233
|
+
|
|
234
|
+
:param account: Account to check the limit for.
|
|
235
|
+
:param rse_id: RSE id to check the limit for.
|
|
236
|
+
:param bytes_: The limit value, in bytes, to set.
|
|
237
|
+
:param session: Database session in use.
|
|
238
|
+
"""
|
|
239
|
+
try:
|
|
240
|
+
stmt = select(
|
|
241
|
+
models.AccountLimit
|
|
242
|
+
).where(
|
|
243
|
+
and_(models.AccountLimit.account == account,
|
|
244
|
+
models.AccountLimit.rse_id == rse_id)
|
|
245
|
+
)
|
|
246
|
+
account_limit = session.execute(stmt).scalar_one()
|
|
247
|
+
account_limit.bytes = bytes_
|
|
248
|
+
except NoResultFound:
|
|
249
|
+
models.AccountLimit(account=account, rse_id=rse_id, bytes=bytes_).save(session=session)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@transactional_session
|
|
253
|
+
def set_global_account_limit(account: "InternalAccount", rse_expression: str, bytes_: int, *, session: "Session") -> None:
|
|
254
|
+
"""
|
|
255
|
+
Sets the global limit for the account on a RSE expression.
|
|
256
|
+
|
|
257
|
+
:param account: Account to check the limit for.
|
|
258
|
+
:param rse_expression: RSE expression to check the limit for.
|
|
259
|
+
:param bytes_: The limit value, in bytes, to set.
|
|
260
|
+
:param session: Database session in use.
|
|
261
|
+
"""
|
|
262
|
+
try:
|
|
263
|
+
stmt = select(
|
|
264
|
+
models.AccountGlobalLimit
|
|
265
|
+
).where(
|
|
266
|
+
and_(models.AccountGlobalLimit.account == account,
|
|
267
|
+
models.AccountGlobalLimit.rse_expression == rse_expression)
|
|
268
|
+
)
|
|
269
|
+
account_limit = session.execute(stmt).scalar_one()
|
|
270
|
+
account_limit.bytes = bytes_
|
|
271
|
+
except NoResultFound:
|
|
272
|
+
models.AccountGlobalLimit(account=account, rse_expression=rse_expression, bytes=bytes_).save(session=session)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@transactional_session
|
|
276
|
+
def delete_local_account_limit(account: "InternalAccount", rse_id: str, *, session: "Session") -> bool:
|
|
277
|
+
"""
|
|
278
|
+
Deletes a local account limit.
|
|
279
|
+
|
|
280
|
+
:param account: Account to delete the limit for.
|
|
281
|
+
:param rse_id: RSE id to delete the limit for.
|
|
282
|
+
:param session: Database session in use.
|
|
283
|
+
:returns: True if something was deleted; False otherwise.
|
|
284
|
+
"""
|
|
285
|
+
try:
|
|
286
|
+
stmt = select(
|
|
287
|
+
models.AccountLimit
|
|
288
|
+
).where(
|
|
289
|
+
and_(models.AccountLimit.account == account,
|
|
290
|
+
models.AccountLimit.rse_id == rse_id)
|
|
291
|
+
)
|
|
292
|
+
result = session.execute(stmt).scalar_one()
|
|
293
|
+
result.delete(session=session)
|
|
294
|
+
return True
|
|
295
|
+
except NoResultFound:
|
|
296
|
+
return False
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
@transactional_session
|
|
300
|
+
def delete_global_account_limit(account: "InternalAccount", rse_expression: str, *, session: "Session") -> bool:
|
|
301
|
+
"""
|
|
302
|
+
Deletes a global account limit.
|
|
303
|
+
|
|
304
|
+
:param account: Account to delete the limit for.
|
|
305
|
+
:param rse_expression: RSE expression to delete the limit for.
|
|
306
|
+
:param session: Database session in use.
|
|
307
|
+
:returns: True if something was deleted; False otherwise.
|
|
308
|
+
"""
|
|
309
|
+
try:
|
|
310
|
+
stmt = select(
|
|
311
|
+
models.AccountGlobalLimit
|
|
312
|
+
).where(
|
|
313
|
+
and_(models.AccountGlobalLimit.account == account,
|
|
314
|
+
models.AccountGlobalLimit.rse_expression == rse_expression)
|
|
315
|
+
)
|
|
316
|
+
result = session.execute(stmt).scalar_one()
|
|
317
|
+
result.delete(session=session)
|
|
318
|
+
return True
|
|
319
|
+
except NoResultFound:
|
|
320
|
+
return False
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
@transactional_session
|
|
324
|
+
def get_local_account_usage(account: "InternalAccount", rse_id: Optional[str] = None, *, session: "Session") -> list["RSELocalAccountUsageDict"]:
|
|
325
|
+
"""
|
|
326
|
+
Read the account usage and connect it with (if available) the account limits of the account.
|
|
327
|
+
|
|
328
|
+
:param account: The account to read.
|
|
329
|
+
:param rse_id: The rse_id to read (If none, get all).
|
|
330
|
+
:param session: Database session in use.
|
|
331
|
+
|
|
332
|
+
:returns: List of dicts {'rse_id', 'rse', 'bytes', 'files', 'bytes_limit', 'bytes_remaining'}
|
|
333
|
+
"""
|
|
334
|
+
|
|
335
|
+
stmt = select(
|
|
336
|
+
models.AccountUsage
|
|
337
|
+
).where(
|
|
338
|
+
models.AccountUsage.account == account
|
|
339
|
+
)
|
|
340
|
+
if not rse_id:
|
|
341
|
+
# All RSESs
|
|
342
|
+
limits = get_local_account_limits(account=account, session=session)
|
|
343
|
+
counters = {c.rse_id: c for c in session.execute(stmt).scalars().all()}
|
|
344
|
+
else:
|
|
345
|
+
# One RSE
|
|
346
|
+
stmt.where(
|
|
347
|
+
models.AccountUsage.rse_id == rse_id
|
|
348
|
+
)
|
|
349
|
+
limits = get_local_account_limits(account=account, rse_ids=[rse_id], session=session)
|
|
350
|
+
counters = {c.rse_id: c for c in session.execute(stmt).scalars().all()}
|
|
351
|
+
result_list = []
|
|
352
|
+
|
|
353
|
+
for rse_id in set(limits).union(counters):
|
|
354
|
+
counter = counters.get(rse_id)
|
|
355
|
+
if counter:
|
|
356
|
+
counter_files = counter.files
|
|
357
|
+
counter_bytes = counter.bytes
|
|
358
|
+
else:
|
|
359
|
+
counter_files = 0
|
|
360
|
+
counter_bytes = 0
|
|
361
|
+
|
|
362
|
+
if counter_bytes > 0 or counter_files > 0 or rse_id in limits.keys():
|
|
363
|
+
result_list.append({
|
|
364
|
+
'rse_id': rse_id,
|
|
365
|
+
'rse': get_rse_name(rse_id=rse_id, session=session),
|
|
366
|
+
'bytes': counter_bytes,
|
|
367
|
+
'files': counter_files,
|
|
368
|
+
'bytes_limit': limits.get(rse_id, 0),
|
|
369
|
+
'bytes_remaining': limits.get(rse_id, 0) - counter_bytes,
|
|
370
|
+
})
|
|
371
|
+
return result_list
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
@transactional_session
|
|
375
|
+
def get_global_account_usage(account: "InternalAccount", rse_expression: Optional[str] = None, *, session: "Session") -> list["RSEGlobalAccountUsageDict"]:
|
|
376
|
+
"""
|
|
377
|
+
Read the account usage and connect it with the global account limits of the account.
|
|
378
|
+
|
|
379
|
+
:param account: The account to read.
|
|
380
|
+
:param rse_expression: The RSE expression (If none, get all).
|
|
381
|
+
:param session: Database session in use.
|
|
382
|
+
|
|
383
|
+
:returns: List of dicts {'rse_expression', 'bytes', 'files' 'bytes_limit', 'bytes_remaining'}
|
|
384
|
+
"""
|
|
385
|
+
result_list = []
|
|
386
|
+
if not rse_expression:
|
|
387
|
+
# All RSE Expressions
|
|
388
|
+
limits = get_global_account_limits(account=account, session=session)
|
|
389
|
+
all_rse_usages = {usage['rse_id']: (usage['bytes'], usage['files']) for usage in get_all_rse_usages_per_account(account=account, session=session)}
|
|
390
|
+
for rse_expression, limit in limits.items():
|
|
391
|
+
usage = 0
|
|
392
|
+
files = 0
|
|
393
|
+
for rse in limit['resolved_rse_ids']:
|
|
394
|
+
usage += all_rse_usages.get(rse, [0])[0]
|
|
395
|
+
files += all_rse_usages.get(rse, [0, 0])[1]
|
|
396
|
+
result_list.append({'rse_expression': rse_expression,
|
|
397
|
+
'bytes': usage, 'files': files,
|
|
398
|
+
'bytes_limit': limit['limit'],
|
|
399
|
+
'bytes_remaining': limit['limit'] - usage})
|
|
400
|
+
else:
|
|
401
|
+
# One RSE Expression
|
|
402
|
+
limit = get_global_account_limit(account=account, rse_expression=rse_expression, session=session)
|
|
403
|
+
vo = account.vo
|
|
404
|
+
resolved_rses = [resolved_rse['id'] for resolved_rse in parse_expression(rse_expression, filter_={'vo': vo}, session=session)]
|
|
405
|
+
stmt = select(
|
|
406
|
+
func.sum(models.AccountUsage.bytes),
|
|
407
|
+
func.sum(models.AccountUsage.files)
|
|
408
|
+
).where(
|
|
409
|
+
and_(models.AccountUsage.account == account,
|
|
410
|
+
models.AccountUsage.rse_id.in_(resolved_rses))
|
|
411
|
+
).group_by(
|
|
412
|
+
models.AccountUsage.account
|
|
413
|
+
)
|
|
414
|
+
usage = session.execute(stmt).first()
|
|
415
|
+
if limit is None:
|
|
416
|
+
limit = 0
|
|
417
|
+
if usage is None:
|
|
418
|
+
usage = 0, 0
|
|
419
|
+
result_list.append({
|
|
420
|
+
'rse_expression': rse_expression,
|
|
421
|
+
'bytes': usage[0], 'files': usage[1],
|
|
422
|
+
'bytes_limit': limit,
|
|
423
|
+
'bytes_remaining': limit - usage[0]
|
|
424
|
+
})
|
|
425
|
+
return result_list
|