rucio 32.8.6__py3-none-any.whl → 35.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/__init__.py +0 -1
- rucio/alembicrevision.py +1 -2
- rucio/client/__init__.py +0 -1
- rucio/client/accountclient.py +45 -25
- rucio/client/accountlimitclient.py +37 -9
- rucio/client/baseclient.py +199 -154
- rucio/client/client.py +2 -3
- rucio/client/configclient.py +19 -6
- rucio/client/credentialclient.py +9 -4
- rucio/client/didclient.py +238 -63
- rucio/client/diracclient.py +13 -5
- rucio/client/downloadclient.py +162 -51
- rucio/client/exportclient.py +4 -4
- rucio/client/fileclient.py +3 -4
- rucio/client/importclient.py +4 -4
- rucio/client/lifetimeclient.py +21 -5
- rucio/client/lockclient.py +18 -8
- rucio/client/{metaclient.py → metaconventionsclient.py} +18 -15
- rucio/client/pingclient.py +0 -1
- rucio/client/replicaclient.py +15 -5
- rucio/client/requestclient.py +35 -19
- rucio/client/rseclient.py +133 -51
- rucio/client/ruleclient.py +29 -22
- rucio/client/scopeclient.py +8 -6
- rucio/client/subscriptionclient.py +47 -35
- rucio/client/touchclient.py +8 -4
- rucio/client/uploadclient.py +166 -82
- rucio/common/__init__.py +0 -1
- rucio/common/cache.py +4 -4
- rucio/common/config.py +52 -47
- rucio/common/constants.py +69 -2
- rucio/common/constraints.py +0 -1
- rucio/common/didtype.py +24 -22
- rucio/common/dumper/__init__.py +70 -41
- rucio/common/dumper/consistency.py +26 -22
- rucio/common/dumper/data_models.py +16 -23
- rucio/common/dumper/path_parsing.py +0 -1
- rucio/common/exception.py +281 -222
- rucio/common/extra.py +0 -1
- rucio/common/logging.py +54 -38
- rucio/common/pcache.py +122 -101
- rucio/common/plugins.py +153 -0
- rucio/common/policy.py +4 -4
- rucio/common/schema/__init__.py +17 -10
- rucio/common/schema/atlas.py +7 -5
- rucio/common/schema/belleii.py +7 -5
- rucio/common/schema/domatpc.py +7 -5
- rucio/common/schema/escape.py +7 -5
- rucio/common/schema/generic.py +8 -6
- rucio/common/schema/generic_multi_vo.py +7 -5
- rucio/common/schema/icecube.py +7 -5
- rucio/common/stomp_utils.py +0 -1
- rucio/common/stopwatch.py +0 -1
- rucio/common/test_rucio_server.py +2 -2
- rucio/common/types.py +262 -17
- rucio/common/utils.py +743 -451
- rucio/core/__init__.py +0 -1
- rucio/core/account.py +99 -29
- rucio/core/account_counter.py +89 -24
- rucio/core/account_limit.py +90 -24
- rucio/core/authentication.py +86 -29
- rucio/core/config.py +108 -38
- rucio/core/credential.py +14 -7
- rucio/core/did.py +680 -782
- rucio/core/did_meta_plugins/__init__.py +8 -6
- rucio/core/did_meta_plugins/did_column_meta.py +17 -12
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +60 -11
- rucio/core/did_meta_plugins/filter_engine.py +90 -50
- rucio/core/did_meta_plugins/json_meta.py +41 -16
- rucio/core/did_meta_plugins/mongo_meta.py +25 -8
- rucio/core/did_meta_plugins/postgres_meta.py +3 -4
- rucio/core/dirac.py +46 -17
- rucio/core/distance.py +66 -43
- rucio/core/exporter.py +5 -5
- rucio/core/heartbeat.py +181 -81
- rucio/core/identity.py +22 -12
- rucio/core/importer.py +23 -12
- rucio/core/lifetime_exception.py +32 -32
- rucio/core/lock.py +244 -142
- rucio/core/message.py +79 -38
- rucio/core/{meta.py → meta_conventions.py} +57 -44
- rucio/core/monitor.py +19 -13
- rucio/core/naming_convention.py +68 -27
- rucio/core/nongrid_trace.py +17 -5
- rucio/core/oidc.py +151 -29
- rucio/core/permission/__init__.py +18 -6
- rucio/core/permission/atlas.py +50 -35
- rucio/core/permission/belleii.py +6 -5
- rucio/core/permission/escape.py +8 -6
- rucio/core/permission/generic.py +82 -80
- rucio/core/permission/generic_multi_vo.py +9 -7
- rucio/core/quarantined_replica.py +91 -58
- rucio/core/replica.py +1303 -772
- rucio/core/replica_sorter.py +10 -12
- rucio/core/request.py +1133 -285
- rucio/core/rse.py +142 -102
- rucio/core/rse_counter.py +49 -18
- rucio/core/rse_expression_parser.py +6 -7
- rucio/core/rse_selector.py +41 -16
- rucio/core/rule.py +1538 -474
- rucio/core/rule_grouping.py +213 -68
- rucio/core/scope.py +50 -22
- rucio/core/subscription.py +92 -44
- rucio/core/topology.py +66 -24
- rucio/core/trace.py +42 -28
- rucio/core/transfer.py +543 -259
- rucio/core/vo.py +36 -18
- rucio/core/volatile_replica.py +59 -32
- rucio/daemons/__init__.py +0 -1
- rucio/daemons/abacus/__init__.py +0 -1
- rucio/daemons/abacus/account.py +29 -19
- rucio/daemons/abacus/collection_replica.py +21 -10
- rucio/daemons/abacus/rse.py +22 -12
- rucio/daemons/atropos/__init__.py +0 -1
- rucio/daemons/atropos/atropos.py +1 -2
- rucio/daemons/auditor/__init__.py +56 -28
- rucio/daemons/auditor/hdfs.py +17 -6
- rucio/daemons/auditor/srmdumps.py +116 -45
- rucio/daemons/automatix/__init__.py +0 -1
- rucio/daemons/automatix/automatix.py +30 -18
- rucio/daemons/badreplicas/__init__.py +0 -1
- rucio/daemons/badreplicas/minos.py +29 -18
- rucio/daemons/badreplicas/minos_temporary_expiration.py +5 -7
- rucio/daemons/badreplicas/necromancer.py +9 -13
- rucio/daemons/bb8/__init__.py +0 -1
- rucio/daemons/bb8/bb8.py +10 -13
- rucio/daemons/bb8/common.py +151 -154
- rucio/daemons/bb8/nuclei_background_rebalance.py +15 -9
- rucio/daemons/bb8/t2_background_rebalance.py +15 -8
- rucio/daemons/c3po/__init__.py +0 -1
- rucio/daemons/c3po/algorithms/__init__.py +0 -1
- rucio/daemons/c3po/algorithms/simple.py +8 -5
- rucio/daemons/c3po/algorithms/t2_free_space.py +10 -7
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +10 -7
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +30 -15
- rucio/daemons/c3po/c3po.py +81 -52
- rucio/daemons/c3po/collectors/__init__.py +0 -1
- rucio/daemons/c3po/collectors/agis.py +17 -17
- rucio/daemons/c3po/collectors/free_space.py +32 -13
- rucio/daemons/c3po/collectors/jedi_did.py +14 -5
- rucio/daemons/c3po/collectors/mock_did.py +11 -6
- rucio/daemons/c3po/collectors/network_metrics.py +12 -4
- rucio/daemons/c3po/collectors/workload.py +21 -19
- rucio/daemons/c3po/utils/__init__.py +0 -1
- rucio/daemons/c3po/utils/dataset_cache.py +15 -5
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +16 -5
- rucio/daemons/c3po/utils/expiring_list.py +6 -7
- rucio/daemons/c3po/utils/popularity.py +5 -2
- rucio/daemons/c3po/utils/timeseries.py +25 -12
- rucio/daemons/cache/__init__.py +0 -1
- rucio/daemons/cache/consumer.py +21 -15
- rucio/daemons/common.py +42 -18
- rucio/daemons/conveyor/__init__.py +0 -1
- rucio/daemons/conveyor/common.py +69 -37
- rucio/daemons/conveyor/finisher.py +83 -46
- rucio/daemons/conveyor/poller.py +101 -69
- rucio/daemons/conveyor/preparer.py +35 -28
- rucio/daemons/conveyor/receiver.py +64 -21
- rucio/daemons/conveyor/stager.py +33 -28
- rucio/daemons/conveyor/submitter.py +71 -47
- rucio/daemons/conveyor/throttler.py +99 -35
- rucio/daemons/follower/__init__.py +0 -1
- rucio/daemons/follower/follower.py +12 -8
- rucio/daemons/hermes/__init__.py +0 -1
- rucio/daemons/hermes/hermes.py +57 -21
- rucio/daemons/judge/__init__.py +0 -1
- rucio/daemons/judge/cleaner.py +27 -17
- rucio/daemons/judge/evaluator.py +31 -18
- rucio/daemons/judge/injector.py +31 -23
- rucio/daemons/judge/repairer.py +28 -18
- rucio/daemons/oauthmanager/__init__.py +0 -1
- rucio/daemons/oauthmanager/oauthmanager.py +7 -8
- rucio/daemons/reaper/__init__.py +0 -1
- rucio/daemons/reaper/dark_reaper.py +15 -9
- rucio/daemons/reaper/reaper.py +109 -67
- rucio/daemons/replicarecoverer/__init__.py +0 -1
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +255 -116
- rucio/{api → daemons/rsedecommissioner}/__init__.py +0 -1
- rucio/daemons/rsedecommissioner/config.py +81 -0
- rucio/daemons/rsedecommissioner/profiles/__init__.py +24 -0
- rucio/daemons/rsedecommissioner/profiles/atlas.py +60 -0
- rucio/daemons/rsedecommissioner/profiles/generic.py +451 -0
- rucio/daemons/rsedecommissioner/profiles/types.py +92 -0
- rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
- rucio/daemons/storage/__init__.py +0 -1
- rucio/daemons/storage/consistency/__init__.py +0 -1
- rucio/daemons/storage/consistency/actions.py +152 -59
- rucio/daemons/tracer/__init__.py +0 -1
- rucio/daemons/tracer/kronos.py +47 -24
- rucio/daemons/transmogrifier/__init__.py +0 -1
- rucio/daemons/transmogrifier/transmogrifier.py +35 -26
- rucio/daemons/undertaker/__init__.py +0 -1
- rucio/daemons/undertaker/undertaker.py +10 -10
- rucio/db/__init__.py +0 -1
- rucio/db/sqla/__init__.py +16 -2
- rucio/db/sqla/constants.py +10 -1
- rucio/db/sqla/migrate_repo/__init__.py +0 -1
- rucio/db/sqla/migrate_repo/env.py +0 -1
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +0 -1
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +1 -3
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +0 -3
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +1 -4
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +0 -1
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +0 -2
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +0 -2
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +0 -1
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +0 -3
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +0 -1
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +1 -2
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +0 -1
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +0 -3
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +1 -4
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +0 -2
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +0 -3
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +1 -2
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +0 -1
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +0 -1
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +0 -2
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +0 -2
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +1 -4
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +1 -4
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +0 -1
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +1 -3
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +0 -2
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +1 -3
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +1 -2
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +1 -3
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +0 -2
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +2 -3
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +1 -4
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +0 -1
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +0 -1
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +0 -1
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +0 -2
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +0 -3
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +0 -2
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +2 -4
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +0 -2
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +1 -4
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +0 -2
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +0 -3
- rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +55 -0
- rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +0 -2
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +0 -2
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +0 -3
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +0 -3
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +1 -3
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +1 -3
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +0 -3
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +0 -3
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +1 -2
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +2 -4
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +0 -1
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +1 -4
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +0 -2
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +1 -2
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +0 -3
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +1 -3
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +0 -3
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +0 -1
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +0 -2
- rucio/db/sqla/migrate_repo/versions/a08fa8de1545_transfer_stats_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +1 -3
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +0 -2
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +1 -4
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +0 -1
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +0 -1
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +1 -4
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +0 -1
- rucio/db/sqla/migrate_repo/versions/b0070f3695c8_add_deletedidmeta_table.py +57 -0
- rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +0 -3
- rucio/db/sqla/migrate_repo/versions/b5493606bbf5_fix_primary_key_for_subscription_history.py +41 -0
- rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +1 -2
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +1 -3
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +1 -5
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +1 -3
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +0 -3
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +1 -3
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +1 -2
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +0 -3
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +1 -4
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +1 -2
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +1 -4
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +1 -3
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +1 -4
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +0 -2
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +1 -3
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +0 -3
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +1 -3
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +0 -1
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +1 -2
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +1 -3
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +0 -2
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +0 -1
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +1 -2
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +0 -3
- rucio/db/sqla/models.py +122 -216
- rucio/db/sqla/sautils.py +12 -5
- rucio/db/sqla/session.py +71 -43
- rucio/db/sqla/types.py +3 -4
- rucio/db/sqla/util.py +91 -69
- rucio/gateway/__init__.py +13 -0
- rucio/{api → gateway}/account.py +119 -46
- rucio/{api → gateway}/account_limit.py +12 -13
- rucio/{api → gateway}/authentication.py +106 -33
- rucio/{api → gateway}/config.py +12 -13
- rucio/{api → gateway}/credential.py +15 -4
- rucio/{api → gateway}/did.py +384 -140
- rucio/{api → gateway}/dirac.py +16 -6
- rucio/{api → gateway}/exporter.py +3 -4
- rucio/{api → gateway}/heartbeat.py +17 -5
- rucio/{api → gateway}/identity.py +63 -19
- rucio/{api → gateway}/importer.py +3 -4
- rucio/{api → gateway}/lifetime_exception.py +35 -10
- rucio/{api → gateway}/lock.py +34 -12
- rucio/{api/meta.py → gateway/meta_conventions.py} +18 -16
- rucio/{api → gateway}/permission.py +4 -5
- rucio/{api → gateway}/quarantined_replica.py +13 -4
- rucio/{api → gateway}/replica.py +12 -11
- rucio/{api → gateway}/request.py +129 -28
- rucio/{api → gateway}/rse.py +11 -12
- rucio/{api → gateway}/rule.py +117 -35
- rucio/{api → gateway}/scope.py +24 -14
- rucio/{api → gateway}/subscription.py +65 -43
- rucio/{api → gateway}/vo.py +17 -7
- rucio/rse/__init__.py +3 -4
- rucio/rse/protocols/__init__.py +0 -1
- rucio/rse/protocols/bittorrent.py +184 -0
- rucio/rse/protocols/cache.py +1 -2
- rucio/rse/protocols/dummy.py +1 -2
- rucio/rse/protocols/gfal.py +12 -10
- rucio/rse/protocols/globus.py +7 -7
- rucio/rse/protocols/gsiftp.py +2 -3
- rucio/rse/protocols/http_cache.py +1 -2
- rucio/rse/protocols/mock.py +1 -2
- rucio/rse/protocols/ngarc.py +1 -2
- rucio/rse/protocols/posix.py +12 -13
- rucio/rse/protocols/protocol.py +116 -52
- rucio/rse/protocols/rclone.py +6 -7
- rucio/rse/protocols/rfio.py +4 -5
- rucio/rse/protocols/srm.py +9 -10
- rucio/rse/protocols/ssh.py +8 -9
- rucio/rse/protocols/storm.py +2 -3
- rucio/rse/protocols/webdav.py +17 -14
- rucio/rse/protocols/xrootd.py +23 -17
- rucio/rse/rsemanager.py +19 -7
- rucio/tests/__init__.py +0 -1
- rucio/tests/common.py +43 -17
- rucio/tests/common_server.py +3 -3
- rucio/transfertool/__init__.py +0 -1
- rucio/transfertool/bittorrent.py +199 -0
- rucio/transfertool/bittorrent_driver.py +52 -0
- rucio/transfertool/bittorrent_driver_qbittorrent.py +133 -0
- rucio/transfertool/fts3.py +250 -138
- rucio/transfertool/fts3_plugins.py +152 -0
- rucio/transfertool/globus.py +9 -8
- rucio/transfertool/globus_library.py +1 -2
- rucio/transfertool/mock.py +21 -12
- rucio/transfertool/transfertool.py +33 -24
- rucio/vcsversion.py +4 -4
- rucio/version.py +5 -13
- rucio/web/__init__.py +0 -1
- rucio/web/rest/__init__.py +0 -1
- rucio/web/rest/flaskapi/__init__.py +0 -1
- rucio/web/rest/flaskapi/authenticated_bp.py +0 -1
- rucio/web/rest/flaskapi/v1/__init__.py +0 -1
- rucio/web/rest/flaskapi/v1/accountlimits.py +15 -13
- rucio/web/rest/flaskapi/v1/accounts.py +49 -48
- rucio/web/rest/flaskapi/v1/archives.py +12 -10
- rucio/web/rest/flaskapi/v1/auth.py +146 -144
- rucio/web/rest/flaskapi/v1/common.py +82 -41
- rucio/web/rest/flaskapi/v1/config.py +5 -6
- rucio/web/rest/flaskapi/v1/credentials.py +7 -8
- rucio/web/rest/flaskapi/v1/dids.py +158 -28
- rucio/web/rest/flaskapi/v1/dirac.py +8 -8
- rucio/web/rest/flaskapi/v1/export.py +3 -5
- rucio/web/rest/flaskapi/v1/heartbeats.py +3 -5
- rucio/web/rest/flaskapi/v1/identities.py +3 -5
- rucio/web/rest/flaskapi/v1/import.py +3 -4
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +6 -9
- rucio/web/rest/flaskapi/v1/locks.py +2 -4
- rucio/web/rest/flaskapi/v1/main.py +10 -2
- rucio/web/rest/flaskapi/v1/{meta.py → meta_conventions.py} +26 -11
- rucio/web/rest/flaskapi/v1/metrics.py +1 -2
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +4 -4
- rucio/web/rest/flaskapi/v1/ping.py +6 -7
- rucio/web/rest/flaskapi/v1/redirect.py +8 -9
- rucio/web/rest/flaskapi/v1/replicas.py +43 -19
- rucio/web/rest/flaskapi/v1/requests.py +178 -21
- rucio/web/rest/flaskapi/v1/rses.py +61 -26
- rucio/web/rest/flaskapi/v1/rules.py +48 -18
- rucio/web/rest/flaskapi/v1/scopes.py +3 -5
- rucio/web/rest/flaskapi/v1/subscriptions.py +22 -18
- rucio/web/rest/flaskapi/v1/traces.py +4 -4
- rucio/web/rest/flaskapi/v1/types.py +20 -0
- rucio/web/rest/flaskapi/v1/vos.py +3 -5
- rucio/web/rest/main.py +0 -1
- rucio/web/rest/metrics.py +0 -1
- rucio/web/rest/ping.py +27 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/ldap.cfg.template +1 -1
- rucio-35.8.0.data/data/rucio/requirements.server.txt +268 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/bootstrap.py +3 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/merge_rucio_configs.py +2 -5
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/tools/reset_database.py +3 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio +87 -85
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-account +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-collection-replica +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-abacus-rse +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-admin +45 -32
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-atropos +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-auditor +13 -7
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-automatix +1 -2
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-bb8 +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-c3po +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-client +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-cache-consumer +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-finisher +1 -2
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-poller +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-preparer +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-receiver +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-stager +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-submitter +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-conveyor-throttler +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dark-reaper +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-dumper +11 -10
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-follower +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-hermes +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-cleaner +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-evaluator +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-injector +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-judge-repairer +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-kronos +1 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-minos-temporary-expiration +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-necromancer +1 -2
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-oauth-manager +2 -3
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-reaper +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-replica-recoverer +6 -7
- rucio-35.8.0.data/scripts/rucio-rse-decommissioner +66 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-storage-consistency-actions +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-transmogrifier +0 -1
- {rucio-32.8.6.data → rucio-35.8.0.data}/scripts/rucio-undertaker +1 -2
- rucio-35.8.0.dist-info/METADATA +72 -0
- rucio-35.8.0.dist-info/RECORD +493 -0
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/WHEEL +1 -1
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/AUTHORS.rst +3 -0
- rucio/api/temporary_did.py +0 -49
- rucio/common/schema/cms.py +0 -478
- rucio/common/schema/lsst.py +0 -423
- rucio/core/permission/cms.py +0 -1166
- rucio/core/temporary_did.py +0 -188
- rucio/daemons/reaper/light_reaper.py +0 -255
- rucio/web/rest/flaskapi/v1/tmp_dids.py +0 -115
- rucio-32.8.6.data/data/rucio/requirements.txt +0 -55
- rucio-32.8.6.data/scripts/rucio-light-reaper +0 -53
- rucio-32.8.6.dist-info/METADATA +0 -83
- rucio-32.8.6.dist-info/RECORD +0 -481
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic.ini.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
- {rucio-32.8.6.data → rucio-35.8.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/licenses/LICENSE +0 -0
- {rucio-32.8.6.dist-info → rucio-35.8.0.dist-info}/top_level.txt +0 -0
rucio/core/rule_grouping.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -14,21 +13,26 @@
|
|
|
14
13
|
# limitations under the License.
|
|
15
14
|
|
|
16
15
|
import logging
|
|
16
|
+
from collections.abc import Sequence
|
|
17
17
|
from datetime import datetime
|
|
18
|
-
from typing import TYPE_CHECKING
|
|
18
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
19
19
|
|
|
20
|
-
from sqlalchemy import func
|
|
21
|
-
from sqlalchemy.
|
|
20
|
+
from sqlalchemy import and_, func, select
|
|
21
|
+
from sqlalchemy.exc import NoResultFound
|
|
22
22
|
|
|
23
23
|
import rucio.core.did
|
|
24
24
|
import rucio.core.lock
|
|
25
25
|
import rucio.core.replica
|
|
26
26
|
from rucio.common.config import config_get_int
|
|
27
|
+
from rucio.common.constants import RseAttr
|
|
27
28
|
from rucio.common.exception import InsufficientTargetRSEs
|
|
28
|
-
from rucio.
|
|
29
|
+
from rucio.common.types import InternalScope
|
|
30
|
+
from rucio.core import account_counter, rse_counter
|
|
31
|
+
from rucio.core import request as request_core
|
|
29
32
|
from rucio.core.rse import get_rse, get_rse_attribute, get_rse_name
|
|
33
|
+
from rucio.core.rse_selector import RSESelector
|
|
30
34
|
from rucio.db.sqla import models
|
|
31
|
-
from rucio.db.sqla.constants import
|
|
35
|
+
from rucio.db.sqla.constants import OBSOLETE, DIDType, LockState, ReplicaState, RequestType, RuleGrouping
|
|
32
36
|
from rucio.db.sqla.session import transactional_session
|
|
33
37
|
|
|
34
38
|
if TYPE_CHECKING:
|
|
@@ -36,7 +40,20 @@ if TYPE_CHECKING:
|
|
|
36
40
|
|
|
37
41
|
|
|
38
42
|
@transactional_session
|
|
39
|
-
def apply_rule_grouping(
|
|
43
|
+
def apply_rule_grouping(
|
|
44
|
+
datasetfiles: Sequence[dict[str, Any]],
|
|
45
|
+
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
46
|
+
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
47
|
+
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
48
|
+
rseselector: RSESelector,
|
|
49
|
+
rule: models.ReplicationRule,
|
|
50
|
+
preferred_rse_ids: Optional[Sequence[str]] = None,
|
|
51
|
+
source_rses: Optional[Sequence[str]] = None,
|
|
52
|
+
*,
|
|
53
|
+
session: "Session"
|
|
54
|
+
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
55
|
+
dict[str, list[dict[str, models.ReplicaLock]]],
|
|
56
|
+
list[dict[str, Any]]]:
|
|
40
57
|
"""
|
|
41
58
|
Apply rule grouping to files.
|
|
42
59
|
|
|
@@ -47,9 +64,9 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
|
|
|
47
64
|
:param rseselector: The RSESelector to be used.
|
|
48
65
|
:param rule: The rule object.
|
|
49
66
|
:param preferred_rse_ids: Preferred RSE's to select.
|
|
50
|
-
:param source_rses: RSE ids of
|
|
67
|
+
:param source_rses: RSE ids of eligible source replicas.
|
|
51
68
|
:param session: Session of the db.
|
|
52
|
-
:returns:
|
|
69
|
+
:returns: Dict of replicas to create, Dict of locks to create, List of transfers to create
|
|
53
70
|
:raises: InsufficientQuota, InsufficientTargetRSEs, RSEOverQuota
|
|
54
71
|
:attention: This method modifies the contents of the locks and replicas input parameters.
|
|
55
72
|
"""
|
|
@@ -58,8 +75,10 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
|
|
|
58
75
|
# replicas_to_create = {'rse_id': [replicas]}
|
|
59
76
|
# transfers_to_create = [{'dest_rse_id':, 'scope':, 'name':, 'request_type':, 'metadata':}]
|
|
60
77
|
|
|
78
|
+
preferred_rse_ids = preferred_rse_ids or []
|
|
79
|
+
source_rses = source_rses or []
|
|
61
80
|
if rule.grouping == RuleGrouping.NONE:
|
|
62
|
-
replicas_to_create, locks_to_create
|
|
81
|
+
replicas_to_create, locks_to_create, \
|
|
63
82
|
transfers_to_create = __apply_rule_to_files_none_grouping(datasetfiles=datasetfiles,
|
|
64
83
|
locks=locks,
|
|
65
84
|
replicas=replicas,
|
|
@@ -70,7 +89,7 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
|
|
|
70
89
|
source_rses=source_rses,
|
|
71
90
|
session=session)
|
|
72
91
|
elif rule.grouping == RuleGrouping.ALL:
|
|
73
|
-
replicas_to_create, locks_to_create
|
|
92
|
+
replicas_to_create, locks_to_create, \
|
|
74
93
|
transfers_to_create = __apply_rule_to_files_all_grouping(datasetfiles=datasetfiles,
|
|
75
94
|
locks=locks,
|
|
76
95
|
replicas=replicas,
|
|
@@ -81,7 +100,7 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
|
|
|
81
100
|
source_rses=source_rses,
|
|
82
101
|
session=session)
|
|
83
102
|
else: # rule.grouping == RuleGrouping.DATASET:
|
|
84
|
-
replicas_to_create, locks_to_create
|
|
103
|
+
replicas_to_create, locks_to_create, \
|
|
85
104
|
transfers_to_create = __apply_rule_to_files_dataset_grouping(datasetfiles=datasetfiles,
|
|
86
105
|
locks=locks,
|
|
87
106
|
replicas=replicas,
|
|
@@ -96,7 +115,19 @@ def apply_rule_grouping(datasetfiles, locks, replicas, source_replicas, rseselec
|
|
|
96
115
|
|
|
97
116
|
|
|
98
117
|
@transactional_session
|
|
99
|
-
def repair_stuck_locks_and_apply_rule_grouping(
|
|
118
|
+
def repair_stuck_locks_and_apply_rule_grouping(
|
|
119
|
+
datasetfiles: Sequence[dict[str, Any]],
|
|
120
|
+
locks: dict[tuple[InternalScope, str], models.ReplicaLock],
|
|
121
|
+
replicas: dict[tuple[InternalScope, str], Any],
|
|
122
|
+
source_replicas: dict[tuple[InternalScope, str], Any],
|
|
123
|
+
rseselector: RSESelector, rule: models.ReplicationRule,
|
|
124
|
+
source_rses: Sequence[str],
|
|
125
|
+
*,
|
|
126
|
+
session: "Session"
|
|
127
|
+
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
128
|
+
dict[str, list[dict[str, models.ReplicaLock]]],
|
|
129
|
+
list[dict[str, Any]],
|
|
130
|
+
dict[str, list[dict[str, models.ReplicaLock]]]]:
|
|
100
131
|
"""
|
|
101
132
|
Apply rule grouping to files.
|
|
102
133
|
|
|
@@ -106,7 +137,7 @@ def repair_stuck_locks_and_apply_rule_grouping(datasetfiles, locks, replicas, so
|
|
|
106
137
|
:param source_replicas: Dict holding all source_replicas.
|
|
107
138
|
:param rseselector: The RSESelector to be used.
|
|
108
139
|
:param rule: The rule object.
|
|
109
|
-
:param source_rses: RSE ids of
|
|
140
|
+
:param source_rses: RSE ids of eligible source_rses.
|
|
110
141
|
:param session: Session of the db.
|
|
111
142
|
:returns: List of replicas to create, List of locks to create, List of transfers to create, List of locks to Delete
|
|
112
143
|
:raises: InsufficientQuota, InsufficientTargetRSEs
|
|
@@ -119,7 +150,7 @@ def repair_stuck_locks_and_apply_rule_grouping(datasetfiles, locks, replicas, so
|
|
|
119
150
|
# locks_to_delete = {'rse_id': [locks]}
|
|
120
151
|
|
|
121
152
|
if rule.grouping == RuleGrouping.NONE:
|
|
122
|
-
replicas_to_create, locks_to_create, transfers_to_create
|
|
153
|
+
replicas_to_create, locks_to_create, transfers_to_create, \
|
|
123
154
|
locks_to_delete = __repair_stuck_locks_with_none_grouping(datasetfiles=datasetfiles,
|
|
124
155
|
locks=locks,
|
|
125
156
|
replicas=replicas,
|
|
@@ -129,7 +160,7 @@ def repair_stuck_locks_and_apply_rule_grouping(datasetfiles, locks, replicas, so
|
|
|
129
160
|
source_rses=source_rses,
|
|
130
161
|
session=session)
|
|
131
162
|
elif rule.grouping == RuleGrouping.ALL:
|
|
132
|
-
replicas_to_create, locks_to_create, transfers_to_create
|
|
163
|
+
replicas_to_create, locks_to_create, transfers_to_create, \
|
|
133
164
|
locks_to_delete = __repair_stuck_locks_with_all_grouping(datasetfiles=datasetfiles,
|
|
134
165
|
locks=locks,
|
|
135
166
|
replicas=replicas,
|
|
@@ -139,7 +170,7 @@ def repair_stuck_locks_and_apply_rule_grouping(datasetfiles, locks, replicas, so
|
|
|
139
170
|
source_rses=source_rses,
|
|
140
171
|
session=session)
|
|
141
172
|
else:
|
|
142
|
-
replicas_to_create, locks_to_create, transfers_to_create
|
|
173
|
+
replicas_to_create, locks_to_create, transfers_to_create, \
|
|
143
174
|
locks_to_delete = __repair_stuck_locks_with_dataset_grouping(datasetfiles=datasetfiles,
|
|
144
175
|
locks=locks,
|
|
145
176
|
replicas=replicas,
|
|
@@ -196,7 +227,20 @@ def create_transfer_dict(dest_rse_id, request_type, scope, name, rule, lock=None
|
|
|
196
227
|
|
|
197
228
|
|
|
198
229
|
@transactional_session
|
|
199
|
-
def __apply_rule_to_files_none_grouping(
|
|
230
|
+
def __apply_rule_to_files_none_grouping(
|
|
231
|
+
datasetfiles: Sequence[dict[str, Any]],
|
|
232
|
+
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
233
|
+
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
234
|
+
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
235
|
+
rseselector: RSESelector,
|
|
236
|
+
rule: models.ReplicationRule,
|
|
237
|
+
preferred_rse_ids: Optional[Sequence[str]] = None,
|
|
238
|
+
source_rses: Optional[Sequence[str]] = None,
|
|
239
|
+
*,
|
|
240
|
+
session: "Session"
|
|
241
|
+
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
242
|
+
dict[str, list[dict[str, models.ReplicaLock]]],
|
|
243
|
+
list[dict[str, Any]]]:
|
|
200
244
|
"""
|
|
201
245
|
Apply a rule to files with NONE grouping.
|
|
202
246
|
|
|
@@ -207,7 +251,7 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
|
|
|
207
251
|
:param rseselector: The RSESelector to be used.
|
|
208
252
|
:param rule: The rule object.
|
|
209
253
|
:param preferred_rse_ids: Preferred RSE's to select.
|
|
210
|
-
:param source_rses: RSE ids of
|
|
254
|
+
:param source_rses: RSE ids of eligible source replicas.
|
|
211
255
|
:param session: Session of the db.
|
|
212
256
|
:returns: replicas_to_create, locks_to_create, transfers_to_create
|
|
213
257
|
:raises: InsufficientAccountLimit, InsufficientTargetRSEs
|
|
@@ -216,6 +260,8 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
|
|
|
216
260
|
locks_to_create = {} # {'rse_id': [locks]}
|
|
217
261
|
replicas_to_create = {} # {'rse_id': [replicas]}
|
|
218
262
|
transfers_to_create = [] # [{'dest_rse_id':, 'scope':, 'name':, 'request_type':, 'metadata':}]
|
|
263
|
+
preferred_rse_ids = preferred_rse_ids or []
|
|
264
|
+
source_rses = source_rses or []
|
|
219
265
|
|
|
220
266
|
for dataset in datasetfiles:
|
|
221
267
|
selected_rse_ids = []
|
|
@@ -223,16 +269,16 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
|
|
|
223
269
|
if len([lock for lock in locks[(file['scope'], file['name'])] if lock.rule_id == rule.id]) == rule.copies:
|
|
224
270
|
# Nothing to do as the file already has the requested amount of locks
|
|
225
271
|
continue
|
|
226
|
-
rse_coverage = {replica.rse_id: file['bytes'] for replica in replicas[(file['scope'], file['name'])] if replica.state in (ReplicaState.AVAILABLE, ReplicaState.COPYING, ReplicaState.TEMPORARY_UNAVAILABLE)}
|
|
272
|
+
rse_coverage = {str(replica.rse_id): file['bytes'] for replica in replicas[(file['scope'], file['name'])] if replica.state in (ReplicaState.AVAILABLE, ReplicaState.COPYING, ReplicaState.TEMPORARY_UNAVAILABLE)}
|
|
227
273
|
if len(preferred_rse_ids) == 0:
|
|
228
274
|
rse_tuples = rseselector.select_rse(size=file['bytes'],
|
|
229
275
|
preferred_rse_ids=rse_coverage.keys(),
|
|
230
|
-
blocklist=[replica.rse_id for replica in replicas[(file['scope'], file['name'])] if replica.state == ReplicaState.BEING_DELETED],
|
|
276
|
+
blocklist=[str(replica.rse_id) for replica in replicas[(file['scope'], file['name'])] if replica.state == ReplicaState.BEING_DELETED],
|
|
231
277
|
existing_rse_size=rse_coverage)
|
|
232
278
|
else:
|
|
233
279
|
rse_tuples = rseselector.select_rse(size=file['bytes'],
|
|
234
280
|
preferred_rse_ids=preferred_rse_ids,
|
|
235
|
-
blocklist=[replica.rse_id for replica in replicas[(file['scope'], file['name'])] if replica.state == ReplicaState.BEING_DELETED],
|
|
281
|
+
blocklist=[str(replica.rse_id) for replica in replicas[(file['scope'], file['name'])] if replica.state == ReplicaState.BEING_DELETED],
|
|
236
282
|
existing_rse_size=rse_coverage)
|
|
237
283
|
for rse_tuple in rse_tuples:
|
|
238
284
|
if len([lock for lock in locks[(file['scope'], file['name'])] if lock.rule_id == rule.id and lock.rse_id == rse_tuple[0]]) == 1:
|
|
@@ -256,9 +302,14 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
|
|
|
256
302
|
if dataset['scope'] is not None:
|
|
257
303
|
for rse_id in list(set(selected_rse_ids)):
|
|
258
304
|
try:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
305
|
+
stmt = select(
|
|
306
|
+
models.CollectionReplica
|
|
307
|
+
).where(
|
|
308
|
+
and_(models.CollectionReplica.scope == dataset['scope'],
|
|
309
|
+
models.CollectionReplica.name == dataset['name'],
|
|
310
|
+
models.CollectionReplica.rse_id == rse_id)
|
|
311
|
+
)
|
|
312
|
+
session.execute(stmt).one()
|
|
262
313
|
except NoResultFound:
|
|
263
314
|
models.CollectionReplica(scope=dataset['scope'],
|
|
264
315
|
name=dataset['name'],
|
|
@@ -277,7 +328,20 @@ def __apply_rule_to_files_none_grouping(datasetfiles, locks, replicas, source_re
|
|
|
277
328
|
|
|
278
329
|
|
|
279
330
|
@transactional_session
|
|
280
|
-
def __apply_rule_to_files_all_grouping(
|
|
331
|
+
def __apply_rule_to_files_all_grouping(
|
|
332
|
+
datasetfiles: Sequence[dict[str, Any]],
|
|
333
|
+
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
334
|
+
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
335
|
+
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
336
|
+
rseselector: RSESelector,
|
|
337
|
+
rule: models.ReplicationRule,
|
|
338
|
+
preferred_rse_ids: Optional[Sequence[str]] = None,
|
|
339
|
+
source_rses: Optional[Sequence[str]] = None,
|
|
340
|
+
*,
|
|
341
|
+
session: "Session"
|
|
342
|
+
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
343
|
+
dict[str, list[dict[str, models.ReplicaLock]]],
|
|
344
|
+
list[dict[str, Any]]]:
|
|
281
345
|
"""
|
|
282
346
|
Apply a rule to files with ALL grouping.
|
|
283
347
|
|
|
@@ -288,7 +352,7 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
|
|
|
288
352
|
:param rseselector: The RSESelector to be used.
|
|
289
353
|
:param rule: The rule object.
|
|
290
354
|
:param preferred_rse_ids: Preferred RSE's to select.
|
|
291
|
-
:param source_rses: RSE ids of
|
|
355
|
+
:param source_rses: RSE ids of eligible source replicas.
|
|
292
356
|
:param session: Session of the db.
|
|
293
357
|
:returns: replicas_to_create, locks_to_create, transfers_to_create
|
|
294
358
|
:raises: InsufficientQuota, InsufficientTargetRSEs
|
|
@@ -298,6 +362,8 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
|
|
|
298
362
|
locks_to_create = {} # {'rse_id': [locks]}
|
|
299
363
|
replicas_to_create = {} # {'rse_id': [replicas]}
|
|
300
364
|
transfers_to_create = [] # [{'dest_rse_id':, 'scope':, 'name':, 'request_type':, 'metadata':}]
|
|
365
|
+
preferred_rse_ids = preferred_rse_ids or []
|
|
366
|
+
source_rses = source_rses or []
|
|
301
367
|
|
|
302
368
|
bytes_ = 0
|
|
303
369
|
rse_coverage = {} # {'rse_id': coverage }
|
|
@@ -351,17 +417,28 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
|
|
|
351
417
|
# Add a DatasetLock to the DB
|
|
352
418
|
if dataset['scope'] is not None:
|
|
353
419
|
try:
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
420
|
+
stmt = select(
|
|
421
|
+
models.DatasetLock
|
|
422
|
+
).where(
|
|
423
|
+
and_(models.DatasetLock.scope == dataset['scope'],
|
|
424
|
+
models.DatasetLock.name == dataset['name'],
|
|
425
|
+
models.DatasetLock.rule_id == rule.id,
|
|
426
|
+
models.DatasetLock.rse_id == rse_tuple[0])
|
|
427
|
+
)
|
|
428
|
+
session.execute(stmt).one()
|
|
358
429
|
except NoResultFound:
|
|
359
430
|
# Get dataset Information
|
|
360
431
|
is_open, bytes_, length = True, 0, 0
|
|
361
432
|
try:
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
433
|
+
stmt = select(
|
|
434
|
+
models.DataIdentifier.is_open,
|
|
435
|
+
models.DataIdentifier.bytes,
|
|
436
|
+
models.DataIdentifier.length
|
|
437
|
+
).where(
|
|
438
|
+
and_(models.DataIdentifier.scope == dataset['scope'],
|
|
439
|
+
models.DataIdentifier.name == dataset['name'])
|
|
440
|
+
)
|
|
441
|
+
is_open, bytes_, length = session.execute(stmt).one()
|
|
365
442
|
except NoResultFound:
|
|
366
443
|
pass
|
|
367
444
|
|
|
@@ -376,9 +453,14 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
|
|
|
376
453
|
# Add a Dataset Replica to the DB
|
|
377
454
|
if dataset['scope'] is not None:
|
|
378
455
|
try:
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
456
|
+
stmt = select(
|
|
457
|
+
models.CollectionReplica
|
|
458
|
+
).where(
|
|
459
|
+
and_(models.CollectionReplica.scope == dataset['scope'],
|
|
460
|
+
models.CollectionReplica.name == dataset['name'],
|
|
461
|
+
models.CollectionReplica.rse_id == rse_tuple[0])
|
|
462
|
+
)
|
|
463
|
+
session.execute(stmt).one()
|
|
382
464
|
except NoResultFound:
|
|
383
465
|
models.CollectionReplica(scope=dataset['scope'],
|
|
384
466
|
name=dataset['name'],
|
|
@@ -397,9 +479,22 @@ def __apply_rule_to_files_all_grouping(datasetfiles, locks, replicas, source_rep
|
|
|
397
479
|
|
|
398
480
|
|
|
399
481
|
@transactional_session
|
|
400
|
-
def __apply_rule_to_files_dataset_grouping(
|
|
482
|
+
def __apply_rule_to_files_dataset_grouping(
|
|
483
|
+
datasetfiles: Sequence[dict[str, Any]],
|
|
484
|
+
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
485
|
+
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
486
|
+
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
487
|
+
rseselector: RSESelector,
|
|
488
|
+
rule: models.ReplicationRule,
|
|
489
|
+
preferred_rse_ids: Optional[Sequence[str]] = None,
|
|
490
|
+
source_rses: Optional[Sequence[str]] = None,
|
|
491
|
+
*,
|
|
492
|
+
session: "Session"
|
|
493
|
+
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
494
|
+
dict[str, list[dict[str, models.ReplicaLock]]],
|
|
495
|
+
list[dict[str, Any]]]:
|
|
401
496
|
"""
|
|
402
|
-
Apply a rule to files with
|
|
497
|
+
Apply a rule to files with DATASET grouping.
|
|
403
498
|
|
|
404
499
|
:param datasetfiles: Dict holding all datasets and files.
|
|
405
500
|
:param locks: Dict holding all locks.
|
|
@@ -408,7 +503,7 @@ def __apply_rule_to_files_dataset_grouping(datasetfiles, locks, replicas, source
|
|
|
408
503
|
:param rseselector: The RSESelector to be used.
|
|
409
504
|
:param rule: The rule object.
|
|
410
505
|
:param preferred_rse_ids: Preferred RSE's to select.
|
|
411
|
-
:param source_rses: RSE ids of
|
|
506
|
+
:param source_rses: RSE ids of eligible source replicas.
|
|
412
507
|
:param session: Session of the db.
|
|
413
508
|
:returns: replicas_to_create, locks_to_create, transfers_to_create
|
|
414
509
|
:raises: InsufficientQuota, InsufficientTargetRSEs
|
|
@@ -417,6 +512,8 @@ def __apply_rule_to_files_dataset_grouping(datasetfiles, locks, replicas, source
|
|
|
417
512
|
locks_to_create = {} # {'rse_id': [locks]}
|
|
418
513
|
replicas_to_create = {} # {'rse_id': [replicas]}
|
|
419
514
|
transfers_to_create = [] # [{'dest_rse_id':, 'scope':, 'name':, 'request_type':, 'metadata':}]
|
|
515
|
+
preferred_rse_ids = preferred_rse_ids or []
|
|
516
|
+
source_rses = source_rses or []
|
|
420
517
|
|
|
421
518
|
for dataset in datasetfiles:
|
|
422
519
|
bytes_ = sum([file['bytes'] for file in dataset['files']])
|
|
@@ -468,17 +565,28 @@ def __apply_rule_to_files_dataset_grouping(datasetfiles, locks, replicas, source
|
|
|
468
565
|
# Add a DatasetLock to the DB
|
|
469
566
|
if dataset['scope'] is not None:
|
|
470
567
|
try:
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
568
|
+
stmt = select(
|
|
569
|
+
models.DatasetLock
|
|
570
|
+
).where(
|
|
571
|
+
and_(models.DatasetLock.scope == dataset['scope'],
|
|
572
|
+
models.DatasetLock.name == dataset['name'],
|
|
573
|
+
models.DatasetLock.rule_id == rule.id,
|
|
574
|
+
models.DatasetLock.rse_id == rse_tuple[0])
|
|
575
|
+
)
|
|
576
|
+
session.execute(stmt).one()
|
|
475
577
|
except NoResultFound:
|
|
476
578
|
# Get dataset Information
|
|
477
579
|
is_open, bytes_, length = True, None, None
|
|
478
580
|
try:
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
581
|
+
stmt = select(
|
|
582
|
+
models.DataIdentifier.is_open,
|
|
583
|
+
models.DataIdentifier.bytes,
|
|
584
|
+
models.DataIdentifier.length
|
|
585
|
+
).where(
|
|
586
|
+
and_(models.DataIdentifier.scope == dataset['scope'],
|
|
587
|
+
models.DataIdentifier.name == dataset['name'])
|
|
588
|
+
)
|
|
589
|
+
is_open, bytes_, length = session.execute(stmt).one()
|
|
482
590
|
except NoResultFound:
|
|
483
591
|
pass
|
|
484
592
|
|
|
@@ -494,9 +602,14 @@ def __apply_rule_to_files_dataset_grouping(datasetfiles, locks, replicas, source
|
|
|
494
602
|
# Add a Dataset Replica to the DB
|
|
495
603
|
if dataset['scope'] is not None:
|
|
496
604
|
try:
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
605
|
+
stmt = select(
|
|
606
|
+
models.CollectionReplica
|
|
607
|
+
).where(
|
|
608
|
+
and_(models.CollectionReplica.scope == dataset['scope'],
|
|
609
|
+
models.CollectionReplica.name == dataset['name'],
|
|
610
|
+
models.CollectionReplica.rse_id == rse_tuple[0])
|
|
611
|
+
)
|
|
612
|
+
session.execute(stmt).one()
|
|
500
613
|
except NoResultFound:
|
|
501
614
|
models.CollectionReplica(scope=dataset['scope'],
|
|
502
615
|
name=dataset['name'],
|
|
@@ -525,7 +638,7 @@ def __repair_stuck_locks_with_none_grouping(datasetfiles, locks, replicas, sourc
|
|
|
525
638
|
:param source_replicas: Dict holding all source_replicas.
|
|
526
639
|
:param rseselector: The RSESelector to be used.
|
|
527
640
|
:param rule: The rule object.
|
|
528
|
-
:param source_rses: RSE ids of
|
|
641
|
+
:param source_rses: RSE ids of eligible source replicas.
|
|
529
642
|
:param session: Session of the db.
|
|
530
643
|
:param logger: Optional decorated logger that can be passed from the calling daemons or servers.
|
|
531
644
|
:returns: replicas_to_create, locks_to_create, transfers_to_create, locks_to_delete
|
|
@@ -563,12 +676,21 @@ def __repair_stuck_locks_with_none_grouping(datasetfiles, locks, replicas, sourc
|
|
|
563
676
|
# Recalculate the replica_lock_cnt
|
|
564
677
|
associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.state in [ReplicaState.AVAILABLE, ReplicaState.TEMPORARY_UNAVAILABLE] and replica.rse_id == lock.rse_id][0]
|
|
565
678
|
associated_replica.tombstone = None
|
|
566
|
-
|
|
679
|
+
stmt = select(
|
|
680
|
+
func.count(models.ReplicaLock.rule_id)
|
|
681
|
+
).select_from(
|
|
682
|
+
models.ReplicaLock
|
|
683
|
+
).where(
|
|
684
|
+
and_(models.ReplicaLock.scope == associated_replica.scope,
|
|
685
|
+
models.ReplicaLock.name == associated_replica.name,
|
|
686
|
+
models.ReplicaLock.rse_id == lock.rse_id)
|
|
687
|
+
)
|
|
688
|
+
associated_replica.lock_cnt = session.execute(stmt).scalar_one()
|
|
567
689
|
continue
|
|
568
690
|
# Check if this is a STUCK lock due to source_replica filtering
|
|
569
691
|
if source_rses:
|
|
570
692
|
associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.rse_id == lock.rse_id][0]
|
|
571
|
-
# Check if there is an
|
|
693
|
+
# Check if there is an eligible source replica for this lock
|
|
572
694
|
if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses) and (selector_rse_dict.get(lock.rse_id, {}).get('availability_write', True) or rule.ignore_availability):
|
|
573
695
|
__update_lock_replica_and_create_transfer(lock=lock,
|
|
574
696
|
replica=associated_replica,
|
|
@@ -632,7 +754,7 @@ def __repair_stuck_locks_with_all_grouping(datasetfiles, locks, replicas, source
|
|
|
632
754
|
:param source_replicas: Dict holding all source_replicas.
|
|
633
755
|
:param rseselector: The RSESelector to be used.
|
|
634
756
|
:param rule: The rule object.
|
|
635
|
-
:param source_rses: RSE ids of
|
|
757
|
+
:param source_rses: RSE ids of eligible source replicas.
|
|
636
758
|
:param session: Session of the db.
|
|
637
759
|
:param logger: Optional decorated logger that can be passed from the calling daemons or servers.
|
|
638
760
|
:returns: replicas_to_create, locks_to_create, transfers_to_create, locks_to_delete
|
|
@@ -670,12 +792,21 @@ def __repair_stuck_locks_with_all_grouping(datasetfiles, locks, replicas, source
|
|
|
670
792
|
# Recalculate the replica_lock_cnt
|
|
671
793
|
associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.state in [ReplicaState.AVAILABLE, ReplicaState.TEMPORARY_UNAVAILABLE] and replica.rse_id == lock.rse_id][0]
|
|
672
794
|
associated_replica.tombstone = None
|
|
673
|
-
|
|
795
|
+
stmt = select(
|
|
796
|
+
func.count(models.ReplicaLock.rule_id)
|
|
797
|
+
).select_from(
|
|
798
|
+
models.ReplicaLock
|
|
799
|
+
).where(
|
|
800
|
+
and_(models.ReplicaLock.scope == associated_replica.scope,
|
|
801
|
+
models.ReplicaLock.name == associated_replica.name,
|
|
802
|
+
models.ReplicaLock.rse_id == lock.rse_id)
|
|
803
|
+
)
|
|
804
|
+
associated_replica.lock_cnt = session.execute(stmt).scalar_one()
|
|
674
805
|
continue
|
|
675
806
|
# Check if this is a STUCK lock due to source_replica filtering
|
|
676
807
|
if source_rses:
|
|
677
808
|
associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.rse_id == lock.rse_id][0]
|
|
678
|
-
# Check if there is an
|
|
809
|
+
# Check if there is an eligible source replica for this lock
|
|
679
810
|
if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses) and (selector_rse_dict.get(lock.rse_id, {}).get('availability_write', True) or rule.ignore_availability):
|
|
680
811
|
__update_lock_replica_and_create_transfer(lock=lock,
|
|
681
812
|
replica=associated_replica,
|
|
@@ -708,7 +839,7 @@ def __repair_stuck_locks_with_dataset_grouping(datasetfiles, locks, replicas, so
|
|
|
708
839
|
:param source_replicas: Dict holding all source_replicas.
|
|
709
840
|
:param rseselector: The RSESelector to be used.
|
|
710
841
|
:param rule: The rule object.
|
|
711
|
-
:param source_rses: RSE ids of
|
|
842
|
+
:param source_rses: RSE ids of eligible source replicas.
|
|
712
843
|
:param session: Session of the db.
|
|
713
844
|
:param logger: Optional decorated logger that can be passed from the calling daemons or servers.
|
|
714
845
|
:returns: replicas_to_create, locks_to_create, transfers_to_create, locks_to_delete
|
|
@@ -746,12 +877,21 @@ def __repair_stuck_locks_with_dataset_grouping(datasetfiles, locks, replicas, so
|
|
|
746
877
|
# Recalculate the replica_lock_cnt
|
|
747
878
|
associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.state in [ReplicaState.AVAILABLE, ReplicaState.TEMPORARY_UNAVAILABLE] and replica.rse_id == lock.rse_id][0]
|
|
748
879
|
associated_replica.tombstone = None
|
|
749
|
-
|
|
880
|
+
stmt = select(
|
|
881
|
+
func.count(models.ReplicaLock.rule_id)
|
|
882
|
+
).select_from(
|
|
883
|
+
models.ReplicaLock
|
|
884
|
+
).where(
|
|
885
|
+
and_(models.ReplicaLock.scope == associated_replica.scope,
|
|
886
|
+
models.ReplicaLock.name == associated_replica.name,
|
|
887
|
+
models.ReplicaLock.rse_id == lock.rse_id)
|
|
888
|
+
)
|
|
889
|
+
associated_replica.lock_cnt = session.execute(stmt).scalar_one()
|
|
750
890
|
continue
|
|
751
891
|
# Check if this is a STUCK lock due to source_replica filtering
|
|
752
892
|
if source_rses:
|
|
753
893
|
associated_replica = [replica for replica in replicas[(file['scope'], file['name'])] if replica.rse_id == lock.rse_id][0]
|
|
754
|
-
# Check if there is an
|
|
894
|
+
# Check if there is an eligible source replica for this lock
|
|
755
895
|
if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses) and (selector_rse_dict.get(lock.rse_id, {}).get('availability_write', True) or rule.ignore_availability):
|
|
756
896
|
__update_lock_replica_and_create_transfer(lock=lock,
|
|
757
897
|
replica=associated_replica,
|
|
@@ -818,7 +958,7 @@ def __create_lock_and_replica(file, dataset, rule, rse_id, staging_area, availab
|
|
|
818
958
|
:param availability_write: Boolean variable if the RSE is write enabled.
|
|
819
959
|
:param locks_to_create: Dictionary of the locks to create.
|
|
820
960
|
:param locks: Dictionary of all locks.
|
|
821
|
-
:param source_rses: RSE ids of
|
|
961
|
+
:param source_rses: RSE ids of eligible source replicas.
|
|
822
962
|
:param replicas_to_create: Dictionary of the replicas to create.
|
|
823
963
|
:param replicas: Dictionary of the replicas.
|
|
824
964
|
:param source_replicas: Dictionary of the source replicas.
|
|
@@ -851,8 +991,8 @@ def __create_lock_and_replica(file, dataset, rule, rse_id, staging_area, availab
|
|
|
851
991
|
session=session))
|
|
852
992
|
|
|
853
993
|
# If staging_required type RSE then set pin to RSE attribute maximum_pin_lifetime
|
|
854
|
-
staging_required = get_rse_attribute(rse_id,
|
|
855
|
-
maximum_pin_lifetime = get_rse_attribute(rse_id,
|
|
994
|
+
staging_required = get_rse_attribute(rse_id, RseAttr.STAGING_REQUIRED, session=session)
|
|
995
|
+
maximum_pin_lifetime = get_rse_attribute(rse_id, RseAttr.MAXIMUM_PIN_LIFETIME, session=session)
|
|
856
996
|
|
|
857
997
|
if staging_required:
|
|
858
998
|
if (not copy_pin_lifetime and maximum_pin_lifetime) or (copy_pin_lifetime and maximum_pin_lifetime and copy_pin_lifetime < int(maximum_pin_lifetime)):
|
|
@@ -900,7 +1040,7 @@ def __create_lock_and_replica(file, dataset, rule, rse_id, staging_area, availab
|
|
|
900
1040
|
available_source_replica = True
|
|
901
1041
|
if source_rses:
|
|
902
1042
|
available_source_replica = False
|
|
903
|
-
# Check if there is an
|
|
1043
|
+
# Check if there is an eligible source replica for this lock
|
|
904
1044
|
if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses):
|
|
905
1045
|
available_source_replica = True
|
|
906
1046
|
new_lock = __create_lock(rule=rule,
|
|
@@ -947,7 +1087,7 @@ def __create_lock_and_replica(file, dataset, rule, rse_id, staging_area, availab
|
|
|
947
1087
|
available_source_replica = True
|
|
948
1088
|
if source_rses:
|
|
949
1089
|
available_source_replica = False
|
|
950
|
-
# Check if there is an
|
|
1090
|
+
# Check if there is an eligible source replica for this lock
|
|
951
1091
|
if set(source_replicas.get((file['scope'], file['name']), [])).intersection(source_rses):
|
|
952
1092
|
available_source_replica = True
|
|
953
1093
|
|
|
@@ -1281,7 +1421,7 @@ def apply_rule(did, rule, rses, source_rses, rseselector, *, session: "Session",
|
|
|
1281
1421
|
datasets.append((did.scope, did.name, ))
|
|
1282
1422
|
elif did.did_type == DIDType.CONTAINER:
|
|
1283
1423
|
for child_dataset in rucio.core.did.list_child_datasets(scope=did.scope, name=did.name, session=session):
|
|
1284
|
-
# ensure
|
|
1424
|
+
# ensure there are no duplicates
|
|
1285
1425
|
newds = (child_dataset['scope'], child_dataset['name'], )
|
|
1286
1426
|
if newds not in datasets:
|
|
1287
1427
|
datasets.append(newds)
|
|
@@ -1450,9 +1590,14 @@ def apply_rule(did, rule, rses, source_rses, rseselector, *, session: "Session",
|
|
|
1450
1590
|
|
|
1451
1591
|
# add dataset replica if not already existing (rule_id is not in PK)
|
|
1452
1592
|
try:
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1593
|
+
stmt = select(
|
|
1594
|
+
models.CollectionReplica
|
|
1595
|
+
).where(
|
|
1596
|
+
and_(models.CollectionReplica.scope == ds_scope,
|
|
1597
|
+
models.CollectionReplica.name == ds_name,
|
|
1598
|
+
models.CollectionReplica.rse_id == u_rse)
|
|
1599
|
+
)
|
|
1600
|
+
session.execute(stmt).one()
|
|
1456
1601
|
except NoResultFound:
|
|
1457
1602
|
models.CollectionReplica(scope=ds_scope, name=ds_name, did_type=DIDType.DATASET,
|
|
1458
1603
|
rse_id=u_rse,
|