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,185 @@
|
|
|
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
|
+
from typing import TYPE_CHECKING
|
|
15
|
+
|
|
16
|
+
from sqlalchemy import and_, delete, select
|
|
17
|
+
from sqlalchemy.exc import NoResultFound
|
|
18
|
+
|
|
19
|
+
from rucio.common.exception import CounterNotFound
|
|
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
|
+
|
|
27
|
+
@transactional_session
|
|
28
|
+
def add_counter(rse_id, *, session: "Session"):
|
|
29
|
+
"""
|
|
30
|
+
Creates the specified counter for a rse_id.
|
|
31
|
+
|
|
32
|
+
:param rse_id: The id of the RSE.
|
|
33
|
+
:param session: The database session in use.
|
|
34
|
+
"""
|
|
35
|
+
models.RSEUsage(rse_id=rse_id, source='rucio', files=0, used=0).\
|
|
36
|
+
save(session=session)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@transactional_session
|
|
40
|
+
def increase(rse_id, files, bytes_, *, session: "Session"):
|
|
41
|
+
"""
|
|
42
|
+
Increments the specified counter by the specified amount.
|
|
43
|
+
|
|
44
|
+
:param rse_id: The id of the RSE.
|
|
45
|
+
:param files: The number of added files.
|
|
46
|
+
:param bytes_: The number of added bytes.
|
|
47
|
+
:param session: The database session in use.
|
|
48
|
+
"""
|
|
49
|
+
models.UpdatedRSECounter(rse_id=rse_id, files=files, bytes=bytes_).\
|
|
50
|
+
save(session=session)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@transactional_session
|
|
54
|
+
def decrease(rse_id, files, bytes_, *, session: "Session"):
|
|
55
|
+
"""
|
|
56
|
+
Decreases the specified counter by the specified amount.
|
|
57
|
+
|
|
58
|
+
:param rse_id: The id of the RSE.
|
|
59
|
+
:param files: The number of removed files.
|
|
60
|
+
:param bytes_: The number of removed bytes.
|
|
61
|
+
:param session: The database session in use.
|
|
62
|
+
"""
|
|
63
|
+
return increase(rse_id=rse_id, files=-files, bytes_=-bytes_, session=session)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@transactional_session
|
|
67
|
+
def del_counter(rse_id, *, session: "Session"):
|
|
68
|
+
"""
|
|
69
|
+
Delete specified counter.
|
|
70
|
+
|
|
71
|
+
:param rse_id: The id of the RSE.
|
|
72
|
+
:param session: The database session in use.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
stmt = delete(
|
|
76
|
+
models.RSEUsage
|
|
77
|
+
).where(
|
|
78
|
+
and_(models.RSEUsage.rse_id == rse_id,
|
|
79
|
+
models.RSEUsage.source == 'rucio')
|
|
80
|
+
).execution_options(
|
|
81
|
+
synchronize_session=False
|
|
82
|
+
)
|
|
83
|
+
session.execute(stmt)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@read_session
|
|
87
|
+
def get_counter(rse_id, *, session: "Session"):
|
|
88
|
+
"""
|
|
89
|
+
Returns current values of the specified counter or raises CounterNotFound if the counter does not exist.
|
|
90
|
+
|
|
91
|
+
:param rse_id: The id of the RSE.
|
|
92
|
+
:param session: The database session in use.
|
|
93
|
+
:returns: A dictionary with total and bytes.
|
|
94
|
+
:raises CounterNotFound: If the counter does not exist.
|
|
95
|
+
:returns: A dictionary with total and bytes.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
stmt = select(
|
|
100
|
+
models.RSEUsage.used,
|
|
101
|
+
models.RSEUsage.files,
|
|
102
|
+
models.RSEUsage.updated_at
|
|
103
|
+
).where(
|
|
104
|
+
and_(models.RSEUsage.rse_id == rse_id,
|
|
105
|
+
models.RSEUsage.source == 'rucio')
|
|
106
|
+
)
|
|
107
|
+
usage_bytes, usage_files, usage_updated_at = session.execute(stmt).one()
|
|
108
|
+
return {
|
|
109
|
+
'bytes': usage_bytes,
|
|
110
|
+
'files': usage_files,
|
|
111
|
+
'updated_at': usage_updated_at
|
|
112
|
+
}
|
|
113
|
+
except NoResultFound:
|
|
114
|
+
raise CounterNotFound()
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@read_session
|
|
118
|
+
def get_updated_rse_counters(total_workers, worker_number, *, session: "Session"):
|
|
119
|
+
"""
|
|
120
|
+
Get updated rse_counters.
|
|
121
|
+
|
|
122
|
+
:param total_workers: Number of total workers.
|
|
123
|
+
:param worker_number: id of the executing worker.
|
|
124
|
+
:param session: Database session in use.
|
|
125
|
+
:returns: List of rse_ids whose rse_counters need to be updated.
|
|
126
|
+
"""
|
|
127
|
+
stmt = select(
|
|
128
|
+
models.UpdatedRSECounter.rse_id
|
|
129
|
+
).distinct(
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
stmt = filter_thread_work(session=session, query=stmt, total_threads=total_workers, thread_id=worker_number, hash_variable='rse_id')
|
|
133
|
+
return session.execute(stmt).scalars().all()
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@transactional_session
|
|
137
|
+
def update_rse_counter(rse_id, *, session: "Session"):
|
|
138
|
+
"""
|
|
139
|
+
Read the updated_rse_counters and update the rse_counter.
|
|
140
|
+
|
|
141
|
+
:param rse_id: The rse_id to update.
|
|
142
|
+
:param session: Database session in use.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
stmt = select(
|
|
146
|
+
models.UpdatedRSECounter
|
|
147
|
+
).where(
|
|
148
|
+
models.UpdatedRSECounter.rse_id == rse_id
|
|
149
|
+
)
|
|
150
|
+
updated_rse_counters = session.execute(stmt).scalars().all()
|
|
151
|
+
sum_bytes = sum([updated_rse_counter.bytes for updated_rse_counter in updated_rse_counters])
|
|
152
|
+
sum_files = sum([updated_rse_counter.files for updated_rse_counter in updated_rse_counters])
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
stmt = select(
|
|
156
|
+
models.RSEUsage
|
|
157
|
+
).where(
|
|
158
|
+
and_(models.RSEUsage.rse_id == rse_id,
|
|
159
|
+
models.RSEUsage.source == 'rucio')
|
|
160
|
+
)
|
|
161
|
+
rse_counter = session.execute(stmt).scalar_one()
|
|
162
|
+
rse_counter.used = (rse_counter.used or 0) + sum_bytes
|
|
163
|
+
rse_counter.files = (rse_counter.files or 0) + sum_files
|
|
164
|
+
except NoResultFound:
|
|
165
|
+
models.RSEUsage(rse_id=rse_id,
|
|
166
|
+
used=sum_bytes,
|
|
167
|
+
files=sum_files,
|
|
168
|
+
source='rucio').save(session=session)
|
|
169
|
+
|
|
170
|
+
for update in updated_rse_counters:
|
|
171
|
+
update.delete(flush=False, session=session)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@transactional_session
|
|
175
|
+
def fill_rse_counter_history_table(*, session: "Session"):
|
|
176
|
+
"""
|
|
177
|
+
Fill the RSE usage history table with the current usage.
|
|
178
|
+
|
|
179
|
+
:param session: Database session in use.
|
|
180
|
+
"""
|
|
181
|
+
stmt = select(
|
|
182
|
+
models.RSEUsage
|
|
183
|
+
)
|
|
184
|
+
for usage in session.execute(stmt).scalars().all():
|
|
185
|
+
models.RSEUsageHistory(rse_id=usage['rse_id'], used=usage['used'], files=usage['files'], source=usage['source']).save(session=session)
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import abc
|
|
16
|
+
import re
|
|
17
|
+
from hashlib import sha256
|
|
18
|
+
from typing import TYPE_CHECKING, Any
|
|
19
|
+
|
|
20
|
+
from dogpile.cache.api import NoValue
|
|
21
|
+
|
|
22
|
+
from rucio.common.cache import MemcacheRegion
|
|
23
|
+
from rucio.common.exception import InvalidRSEExpression, RSEWriteBlocked
|
|
24
|
+
from rucio.core.rse import get_rse_attribute, get_rses_with_attribute, list_rses
|
|
25
|
+
from rucio.db.sqla.session import transactional_session
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from sqlalchemy.orm import Session
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
DEFAULT_RSE_ATTRIBUTE = r'([A-Za-z0-9]+([_-][A-Za-z0-9]+)*)'
|
|
32
|
+
RSE_ATTRIBUTE = r'([A-Za-z0-9\._-]+[=<>][A-Za-z0-9_-]+)'
|
|
33
|
+
PRIMITIVE = r'(\(*(%s|%s|%s)\)*)' % (RSE_ATTRIBUTE, DEFAULT_RSE_ATTRIBUTE, r'\*')
|
|
34
|
+
UNION = r'(\|%s)' % (PRIMITIVE)
|
|
35
|
+
INTERSECTION = r'(\&%s)' % (PRIMITIVE)
|
|
36
|
+
COMPLEMENT = r'(\\%s)' % (PRIMITIVE)
|
|
37
|
+
|
|
38
|
+
PATTERN = r'^%s(%s|%s|%s)*' % (PRIMITIVE, UNION, INTERSECTION, COMPLEMENT)
|
|
39
|
+
|
|
40
|
+
REGION = MemcacheRegion(expiration_time=600)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@transactional_session
|
|
44
|
+
def parse_expression(expression, filter_=None, *, session: "Session"):
|
|
45
|
+
"""
|
|
46
|
+
Parse a RSE expression and return the list of RSE dictionaries.
|
|
47
|
+
|
|
48
|
+
:param expression: RSE expression, e.g: 'CERN|BNL'.
|
|
49
|
+
:param filter_: Availability filter (dictionary) used for the RSEs. e.g.: {'availability_write': True}
|
|
50
|
+
:param session: Database session in use.
|
|
51
|
+
:returns: A list of rse dictionaries.
|
|
52
|
+
:raises: InvalidRSEExpression, RSENotFound, RSEWriteBlocked
|
|
53
|
+
"""
|
|
54
|
+
result = REGION.get(sha256(expression.encode()).hexdigest())
|
|
55
|
+
if type(result) is NoValue:
|
|
56
|
+
# Evaluate the correctness of the parentheses
|
|
57
|
+
parantheses_open_count = 0
|
|
58
|
+
parantheses_close_count = 0
|
|
59
|
+
for char in expression:
|
|
60
|
+
if (char == '('):
|
|
61
|
+
parantheses_open_count += 1
|
|
62
|
+
elif (char == ')'):
|
|
63
|
+
parantheses_close_count += 1
|
|
64
|
+
if (parantheses_close_count > parantheses_open_count):
|
|
65
|
+
raise InvalidRSEExpression('Problem with parentheses.')
|
|
66
|
+
if (parantheses_open_count != parantheses_close_count):
|
|
67
|
+
raise InvalidRSEExpression('Problem with parentheses.')
|
|
68
|
+
|
|
69
|
+
# Check the expression pattern
|
|
70
|
+
match = re.match(PATTERN, expression)
|
|
71
|
+
if match is None:
|
|
72
|
+
raise InvalidRSEExpression('Expression does not comply to RSE Expression syntax')
|
|
73
|
+
else:
|
|
74
|
+
if match.group() != expression:
|
|
75
|
+
raise InvalidRSEExpression('Expression does not comply to RSE Expression syntax')
|
|
76
|
+
result_tuple = __resolve_term_expression(expression)[0].resolve_elements(session=session)
|
|
77
|
+
# result_tuple = ([rse_ids], {rse_id: {rse_info}})
|
|
78
|
+
result = []
|
|
79
|
+
for rse in list(result_tuple[0]):
|
|
80
|
+
result.append(result_tuple[1][rse])
|
|
81
|
+
REGION.set(sha256(expression.encode()).hexdigest(), result)
|
|
82
|
+
|
|
83
|
+
# Filter for VO
|
|
84
|
+
vo_result = []
|
|
85
|
+
if filter_ and filter_.get('vo'):
|
|
86
|
+
filter_ = filter_.copy() # Make a copy so we can pop('vo') without affecting the object `filter` outside this function
|
|
87
|
+
vo = filter_.pop('vo')
|
|
88
|
+
for rse in result:
|
|
89
|
+
if rse.get('vo') == vo:
|
|
90
|
+
vo_result.append(rse)
|
|
91
|
+
else:
|
|
92
|
+
vo_result = result
|
|
93
|
+
|
|
94
|
+
if not vo_result:
|
|
95
|
+
raise InvalidRSEExpression('RSE Expression resulted in an empty set.')
|
|
96
|
+
|
|
97
|
+
# Filter
|
|
98
|
+
final_result = []
|
|
99
|
+
if filter_:
|
|
100
|
+
for rse in vo_result:
|
|
101
|
+
if filter_.get('availability_write', False):
|
|
102
|
+
if rse.get('availability_write'):
|
|
103
|
+
final_result.append(rse)
|
|
104
|
+
if not final_result:
|
|
105
|
+
raise RSEWriteBlocked('RSE excluded; not available for writing.')
|
|
106
|
+
else:
|
|
107
|
+
final_result = vo_result
|
|
108
|
+
|
|
109
|
+
# final_result = [{rse-info}]
|
|
110
|
+
return final_result
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def __resolve_term_expression(expression):
|
|
114
|
+
"""
|
|
115
|
+
Resolves a Term Expression and returns an object of type BaseExpressionElement
|
|
116
|
+
|
|
117
|
+
:param subexpression: String of the term expression.
|
|
118
|
+
:returns: Tuple of BaseExpressionElement, term Expression string
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
left_term = None
|
|
122
|
+
operator = None
|
|
123
|
+
original_expression = expression
|
|
124
|
+
|
|
125
|
+
while True:
|
|
126
|
+
if len(expression) == 0:
|
|
127
|
+
return (left_term, original_expression)
|
|
128
|
+
elif expression[0] == "(":
|
|
129
|
+
if left_term is None:
|
|
130
|
+
left_term, termexpression = __resolve_term_expression(__extract_term(expression))
|
|
131
|
+
expression = expression[len(termexpression) + 2:]
|
|
132
|
+
continue
|
|
133
|
+
else:
|
|
134
|
+
right_term, termexpression = __resolve_term_expression(__extract_term(expression))
|
|
135
|
+
expression = expression[len(termexpression) + 2:]
|
|
136
|
+
operator.set_left_term(left_term)
|
|
137
|
+
operator.set_right_term(right_term)
|
|
138
|
+
left_term = operator
|
|
139
|
+
operator = None
|
|
140
|
+
continue
|
|
141
|
+
elif expression[0] == "\\":
|
|
142
|
+
operator = ComplementOperator()
|
|
143
|
+
expression = expression[1:]
|
|
144
|
+
continue
|
|
145
|
+
elif expression[0] == "&":
|
|
146
|
+
operator = IntersectOperator()
|
|
147
|
+
expression = expression[1:]
|
|
148
|
+
continue
|
|
149
|
+
elif expression[0] == "|":
|
|
150
|
+
operator = UnionOperator()
|
|
151
|
+
expression = expression[1:]
|
|
152
|
+
continue
|
|
153
|
+
else:
|
|
154
|
+
if (left_term is None):
|
|
155
|
+
left_term, primitiveexpression = __resolve_primitive_expression(expression)
|
|
156
|
+
expression = expression[len(primitiveexpression):]
|
|
157
|
+
continue
|
|
158
|
+
else:
|
|
159
|
+
right_term, primitiveexpression = __resolve_primitive_expression(expression)
|
|
160
|
+
expression = expression[len(primitiveexpression):]
|
|
161
|
+
operator.set_left_term(left_term)
|
|
162
|
+
operator.set_right_term(right_term)
|
|
163
|
+
left_term = operator
|
|
164
|
+
operator = None
|
|
165
|
+
continue
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def __resolve_primitive_expression(expression):
|
|
169
|
+
"""
|
|
170
|
+
Resolve a primitive expression and return a RSEAttribute object
|
|
171
|
+
|
|
172
|
+
:param expression: String of the expression
|
|
173
|
+
:returns: Tuple of RSEAttribute, primitive expression
|
|
174
|
+
"""
|
|
175
|
+
primitiveexpression = re.match(PRIMITIVE, expression).group()
|
|
176
|
+
if ('=' in primitiveexpression):
|
|
177
|
+
keyvalue = primitiveexpression.split("=")
|
|
178
|
+
return (RSEAttributeEqualCheck(keyvalue[0], keyvalue[1]), primitiveexpression)
|
|
179
|
+
elif ('<' in primitiveexpression):
|
|
180
|
+
keyvalue = primitiveexpression.split("<")
|
|
181
|
+
return (RSEAttributeSmallerCheck(keyvalue[0], keyvalue[1]), primitiveexpression)
|
|
182
|
+
elif ('>' in primitiveexpression):
|
|
183
|
+
keyvalue = primitiveexpression.split(">")
|
|
184
|
+
return (RSEAttributeLargerCheck(keyvalue[0], keyvalue[1]), primitiveexpression)
|
|
185
|
+
elif ('*' in primitiveexpression):
|
|
186
|
+
return (RSEAll(), primitiveexpression)
|
|
187
|
+
else:
|
|
188
|
+
return (RSEAttributeEqualCheck(key=primitiveexpression), primitiveexpression)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def __extract_term(expression):
|
|
192
|
+
"""
|
|
193
|
+
Extract a term from an expression with parentheses
|
|
194
|
+
|
|
195
|
+
:param expression: The expression starting with a '('
|
|
196
|
+
:return: The extracted term string
|
|
197
|
+
"""
|
|
198
|
+
open_parantheses = 0
|
|
199
|
+
i = 0
|
|
200
|
+
for char in expression:
|
|
201
|
+
if (char == '('):
|
|
202
|
+
open_parantheses += 1
|
|
203
|
+
elif (char == ')'):
|
|
204
|
+
open_parantheses -= 1
|
|
205
|
+
if (open_parantheses == 0):
|
|
206
|
+
return expression[1:i]
|
|
207
|
+
i = i + 1
|
|
208
|
+
raise SystemError('This point in the code should not be reachable')
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class BaseExpressionElement(metaclass=abc.ABCMeta):
|
|
212
|
+
@abc.abstractmethod
|
|
213
|
+
def resolve_elements(self, session):
|
|
214
|
+
"""
|
|
215
|
+
Resolve the ExpressionElement and return a set of RSE ids
|
|
216
|
+
|
|
217
|
+
:param session: Database session in use
|
|
218
|
+
:returns: (Set of RSE ids, Dictionary of RSE dicts)
|
|
219
|
+
:rtype: (Set of Strings, Dictionary of RSE dicts organized by rse_id)
|
|
220
|
+
"""
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class RSEAll(BaseExpressionElement):
|
|
225
|
+
"""
|
|
226
|
+
Representation of all RSEs
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
def resolve_elements(self, session):
|
|
230
|
+
"""
|
|
231
|
+
Inherited from :py:func:`BaseExpressionElement.resolve_elements`
|
|
232
|
+
"""
|
|
233
|
+
output = list_rses(session=session)
|
|
234
|
+
if not output:
|
|
235
|
+
return (set(), {})
|
|
236
|
+
rse_dict = {}
|
|
237
|
+
for rse in output:
|
|
238
|
+
rse_dict[rse['id']] = rse
|
|
239
|
+
return (set([rse['id'] for rse in output]), rse_dict)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class RSEAttributeEqualCheck(BaseExpressionElement):
|
|
243
|
+
"""
|
|
244
|
+
Representation of an RSE Attribute with Equal Check
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
def __init__(self, key, value=True):
|
|
248
|
+
"""
|
|
249
|
+
Creates an RSEAttribute representation
|
|
250
|
+
|
|
251
|
+
:param key: Key of the RSE Attribute.
|
|
252
|
+
:param value: Value of the RSE Attribute.
|
|
253
|
+
"""
|
|
254
|
+
self.key = key
|
|
255
|
+
self.value = value
|
|
256
|
+
|
|
257
|
+
def resolve_elements(self, session):
|
|
258
|
+
"""
|
|
259
|
+
Inherited from :py:func:`BaseExpressionElement.resolve_elements`
|
|
260
|
+
"""
|
|
261
|
+
output = list_rses({self.key: self.value}, session=session)
|
|
262
|
+
if not output:
|
|
263
|
+
return (set(), {})
|
|
264
|
+
rse_dict = {}
|
|
265
|
+
for rse in output:
|
|
266
|
+
rse_dict[rse['id']] = rse
|
|
267
|
+
return (set([rse['id'] for rse in output]), rse_dict)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class RSEAttributeSmallerCheck(BaseExpressionElement):
|
|
271
|
+
"""
|
|
272
|
+
Representation of an RSE Attribute with Smaller (<) Check
|
|
273
|
+
"""
|
|
274
|
+
|
|
275
|
+
def __init__(self, key, value=True):
|
|
276
|
+
"""
|
|
277
|
+
Creates an RSEAttribute representation
|
|
278
|
+
|
|
279
|
+
:param key: Key of the RSE Attribute.
|
|
280
|
+
:param value: Value of the RSE Attribute.
|
|
281
|
+
"""
|
|
282
|
+
self.key = key
|
|
283
|
+
self.value = value
|
|
284
|
+
|
|
285
|
+
def resolve_elements(self, session):
|
|
286
|
+
"""
|
|
287
|
+
Inherited from :py:func:`BaseExpressionElement.resolve_elements`
|
|
288
|
+
"""
|
|
289
|
+
rse_list: list[dict[str, Any]] = get_rses_with_attribute(key=self.key, session=session)
|
|
290
|
+
if not rse_list:
|
|
291
|
+
return (set(), {})
|
|
292
|
+
|
|
293
|
+
output = []
|
|
294
|
+
rse_dict = {}
|
|
295
|
+
for rse in rse_list:
|
|
296
|
+
try:
|
|
297
|
+
if float(get_rse_attribute(rse['id'], self.key, session=session)) < float(self.value): # type: ignore (get_rse_attribute could return None)
|
|
298
|
+
rse_dict[rse['id']] = rse
|
|
299
|
+
output.append(rse['id'])
|
|
300
|
+
except ValueError:
|
|
301
|
+
continue
|
|
302
|
+
return (set(output), rse_dict)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class RSEAttributeLargerCheck(BaseExpressionElement):
|
|
306
|
+
"""
|
|
307
|
+
Representation of an RSE Attribute with Larger (>) Check
|
|
308
|
+
"""
|
|
309
|
+
|
|
310
|
+
def __init__(self, key, value=True):
|
|
311
|
+
"""
|
|
312
|
+
Creates an RSEAttribute representation
|
|
313
|
+
|
|
314
|
+
:param key: Key of the RSE Attribute.
|
|
315
|
+
:param value: Value of the RSE Attribute.
|
|
316
|
+
"""
|
|
317
|
+
self.key = key
|
|
318
|
+
self.value = value
|
|
319
|
+
|
|
320
|
+
def resolve_elements(self, session):
|
|
321
|
+
"""
|
|
322
|
+
Inherited from :py:func:`BaseExpressionElement.resolve_elements`
|
|
323
|
+
"""
|
|
324
|
+
rse_list: list[dict[str, Any]] = get_rses_with_attribute(key=self.key, session=session)
|
|
325
|
+
if not rse_list:
|
|
326
|
+
return (set(), {})
|
|
327
|
+
|
|
328
|
+
output = []
|
|
329
|
+
rse_dict = {}
|
|
330
|
+
for rse in rse_list:
|
|
331
|
+
try:
|
|
332
|
+
if float(get_rse_attribute(rse['id'], self.key, session=session)) > float(self.value): # type: ignore (get_rse_attribute could return None)
|
|
333
|
+
rse_dict[rse['id']] = rse
|
|
334
|
+
output.append(rse['id'])
|
|
335
|
+
except ValueError:
|
|
336
|
+
continue
|
|
337
|
+
return (set(output), rse_dict)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class BaseRSEOperator(BaseExpressionElement, metaclass=abc.ABCMeta):
|
|
341
|
+
@abc.abstractmethod
|
|
342
|
+
def set_left_term(self, left_term):
|
|
343
|
+
"""
|
|
344
|
+
Set the left site of the term
|
|
345
|
+
|
|
346
|
+
:param left_term: Left term
|
|
347
|
+
"""
|
|
348
|
+
pass
|
|
349
|
+
|
|
350
|
+
@abc.abstractmethod
|
|
351
|
+
def set_right_term(self, right_term):
|
|
352
|
+
"""
|
|
353
|
+
Set the right site of the term
|
|
354
|
+
|
|
355
|
+
:param left_term: Left term
|
|
356
|
+
"""
|
|
357
|
+
pass
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class ComplementOperator(BaseRSEOperator):
|
|
361
|
+
"""
|
|
362
|
+
Representation of the complement operator
|
|
363
|
+
"""
|
|
364
|
+
|
|
365
|
+
def __init__(self):
|
|
366
|
+
"""
|
|
367
|
+
Create a ComplementOperator representation
|
|
368
|
+
"""
|
|
369
|
+
|
|
370
|
+
self.left_term = None
|
|
371
|
+
self.right_term = None
|
|
372
|
+
|
|
373
|
+
def set_left_term(self, left_term):
|
|
374
|
+
"""
|
|
375
|
+
Inherited from :py:func:`BaseRSEOperator.set_left_term`
|
|
376
|
+
"""
|
|
377
|
+
self.left_term = left_term
|
|
378
|
+
|
|
379
|
+
def set_right_term(self, right_term):
|
|
380
|
+
"""
|
|
381
|
+
Inherited from :py:func:`BaseRSEOperator.set_right_term`
|
|
382
|
+
"""
|
|
383
|
+
self.right_term = right_term
|
|
384
|
+
|
|
385
|
+
def resolve_elements(self, session):
|
|
386
|
+
"""
|
|
387
|
+
Inherited from :py:func:`BaseExpressionElement.resolve_elements`
|
|
388
|
+
"""
|
|
389
|
+
left_term_tuple = self.left_term.resolve_elements(session=session)
|
|
390
|
+
right_term_tuple = self.right_term.resolve_elements(session=session)
|
|
391
|
+
return (left_term_tuple[0] - right_term_tuple[0], dict(list(left_term_tuple[1].items()) + list(right_term_tuple[1].items())))
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
class UnionOperator(BaseRSEOperator):
|
|
395
|
+
"""
|
|
396
|
+
Representation of the or operator
|
|
397
|
+
"""
|
|
398
|
+
|
|
399
|
+
def __init__(self):
|
|
400
|
+
"""
|
|
401
|
+
Create a UnionOperator representation
|
|
402
|
+
"""
|
|
403
|
+
|
|
404
|
+
self.left_term = None
|
|
405
|
+
self.right_term = None
|
|
406
|
+
|
|
407
|
+
def set_left_term(self, left_term):
|
|
408
|
+
"""
|
|
409
|
+
Inherited from :py:func:`BaseRSEOperator.set_left_term`
|
|
410
|
+
"""
|
|
411
|
+
self.left_term = left_term
|
|
412
|
+
|
|
413
|
+
def set_right_term(self, right_term):
|
|
414
|
+
"""
|
|
415
|
+
Inherited from :py:func:`BaseRSEOperator.set_right_term`
|
|
416
|
+
"""
|
|
417
|
+
self.right_term = right_term
|
|
418
|
+
|
|
419
|
+
def resolve_elements(self, session):
|
|
420
|
+
"""
|
|
421
|
+
Inherited from :py:func:`BaseExpressionElement.resolve_elements`
|
|
422
|
+
"""
|
|
423
|
+
left_term_tuple = self.left_term.resolve_elements(session=session)
|
|
424
|
+
right_term_tuple = self.right_term.resolve_elements(session=session)
|
|
425
|
+
return (left_term_tuple[0] | right_term_tuple[0], dict(list(left_term_tuple[1].items()) + list(right_term_tuple[1].items())))
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
class IntersectOperator(BaseRSEOperator):
|
|
429
|
+
"""
|
|
430
|
+
Representation of the intersect operator
|
|
431
|
+
"""
|
|
432
|
+
|
|
433
|
+
def __init__(self):
|
|
434
|
+
"""
|
|
435
|
+
Create a IntersectOperator representation
|
|
436
|
+
"""
|
|
437
|
+
|
|
438
|
+
self.left_term = None
|
|
439
|
+
self.right_term = None
|
|
440
|
+
|
|
441
|
+
def set_left_term(self, left_term):
|
|
442
|
+
"""
|
|
443
|
+
Inherited from :py:func:`BaseRSEOperator.set_left_term`
|
|
444
|
+
"""
|
|
445
|
+
self.left_term = left_term
|
|
446
|
+
|
|
447
|
+
def set_right_term(self, right_term):
|
|
448
|
+
"""
|
|
449
|
+
Inherited from :py:func:`BaseRSEOperator.set_right_term`
|
|
450
|
+
"""
|
|
451
|
+
self.right_term = right_term
|
|
452
|
+
|
|
453
|
+
def resolve_elements(self, session):
|
|
454
|
+
"""
|
|
455
|
+
Inherited from :py:func:`BaseExpressionElement.resolve_elements`
|
|
456
|
+
"""
|
|
457
|
+
left_term_tuple = self.left_term.resolve_elements(session=session)
|
|
458
|
+
right_term_tuple = self.right_term.resolve_elements(session=session)
|
|
459
|
+
return (left_term_tuple[0] & right_term_tuple[0], dict(list(left_term_tuple[1].items()) + list(right_term_tuple[1].items())))
|