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/daemons/bb8/common.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,43 +13,50 @@
|
|
|
14
13
|
# limitations under the License.
|
|
15
14
|
|
|
16
15
|
import logging
|
|
17
|
-
from datetime import
|
|
16
|
+
from datetime import date, datetime, timedelta
|
|
18
17
|
from string import Template
|
|
18
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, Union
|
|
19
19
|
|
|
20
20
|
from requests import get
|
|
21
|
-
from sqlalchemy import
|
|
22
|
-
from sqlalchemy.orm import aliased
|
|
23
|
-
from sqlalchemy.sql.expression import case, select
|
|
21
|
+
from sqlalchemy import BigInteger, and_, case, cast, false, func, or_, select
|
|
22
|
+
from sqlalchemy.orm import Session, aliased
|
|
24
23
|
|
|
25
|
-
from rucio.common.config import config_get,
|
|
24
|
+
from rucio.common.config import config_get, config_get_bool, config_get_int
|
|
26
25
|
from rucio.common.exception import (
|
|
27
|
-
InsufficientTargetRSEs,
|
|
28
|
-
RuleNotFound,
|
|
29
26
|
DuplicateRule,
|
|
30
27
|
InsufficientAccountLimit,
|
|
28
|
+
InsufficientTargetRSEs,
|
|
29
|
+
RuleNotFound,
|
|
31
30
|
)
|
|
32
31
|
from rucio.common.types import InternalAccount, InternalScope
|
|
33
32
|
from rucio.core.lock import get_dataset_locks
|
|
34
|
-
from rucio.core.rse import
|
|
33
|
+
from rucio.core.rse import get_rse_name, get_rse_vo, list_rse_attributes
|
|
35
34
|
from rucio.core.rse_expression_parser import parse_expression
|
|
36
35
|
from rucio.core.rse_selector import RSESelector
|
|
37
|
-
from rucio.core.rule import
|
|
36
|
+
from rucio.core.rule import add_rule, get_rule, update_rule
|
|
38
37
|
from rucio.db.sqla import models
|
|
39
|
-
from rucio.db.sqla.constants import DIDType,
|
|
40
|
-
from rucio.db.sqla.session import
|
|
38
|
+
from rucio.db.sqla.constants import DIDType, LockState, RuleGrouping, RuleState
|
|
39
|
+
from rucio.db.sqla.session import read_session, transactional_session
|
|
40
|
+
|
|
41
|
+
if TYPE_CHECKING:
|
|
42
|
+
from collections.abc import Mapping, Sequence
|
|
43
|
+
|
|
44
|
+
from sqlalchemy.engine import Row
|
|
45
|
+
|
|
46
|
+
from rucio.common.types import LoggerFunction
|
|
41
47
|
|
|
42
48
|
|
|
43
49
|
@transactional_session
|
|
44
50
|
def rebalance_rule(
|
|
45
|
-
parent_rule,
|
|
46
|
-
activity,
|
|
47
|
-
rse_expression,
|
|
48
|
-
priority,
|
|
49
|
-
source_replica_expression="*\\bb8-enabled=false",
|
|
50
|
-
comment=None,
|
|
51
|
+
parent_rule: "Mapping[str, Any]",
|
|
52
|
+
activity: str,
|
|
53
|
+
rse_expression: str,
|
|
54
|
+
priority: int,
|
|
55
|
+
source_replica_expression: str = "*\\bb8-enabled=false",
|
|
56
|
+
comment: Optional[str] = None,
|
|
51
57
|
*,
|
|
52
|
-
session,
|
|
53
|
-
):
|
|
58
|
+
session: Session,
|
|
59
|
+
) -> Optional[list[str]]:
|
|
54
60
|
"""
|
|
55
61
|
Rebalance a replication rule to a new RSE
|
|
56
62
|
:param parent_rule: Replication rule to be rebalanced.
|
|
@@ -117,7 +123,10 @@ def rebalance_rule(
|
|
|
117
123
|
return child_rule
|
|
118
124
|
|
|
119
125
|
|
|
120
|
-
def __dump_url(
|
|
126
|
+
def __dump_url(
|
|
127
|
+
rse_id: str,
|
|
128
|
+
logger: "LoggerFunction" = logging.log
|
|
129
|
+
) -> Union[list[str], Literal[False]]:
|
|
121
130
|
"""
|
|
122
131
|
getting potential urls of the dump over last week
|
|
123
132
|
:param rse_id: RSE where the dump is released.
|
|
@@ -173,7 +182,11 @@ def __dump_url(rse_id, logger=logging.log):
|
|
|
173
182
|
return urls
|
|
174
183
|
|
|
175
184
|
|
|
176
|
-
def _list_rebalance_rule_candidates_dump(
|
|
185
|
+
def _list_rebalance_rule_candidates_dump(
|
|
186
|
+
rse_id: str,
|
|
187
|
+
mode: Optional[str] = None,
|
|
188
|
+
logger: "LoggerFunction" = logging.log
|
|
189
|
+
) -> list[tuple]:
|
|
177
190
|
"""
|
|
178
191
|
Download dump to temporary directory
|
|
179
192
|
:param rse_id: RSE of the source.
|
|
@@ -185,11 +198,11 @@ def _list_rebalance_rule_candidates_dump(rse_id, mode=None, logger=logging.log):
|
|
|
185
198
|
candidates = []
|
|
186
199
|
rules = {}
|
|
187
200
|
rse_dump_urls = __dump_url(rse_id=rse_id)
|
|
188
|
-
rse_dump_urls.reverse()
|
|
189
201
|
resp = None
|
|
190
202
|
if not rse_dump_urls:
|
|
191
203
|
logger(logging.DEBUG, "URL of the dump was not built from template.")
|
|
192
204
|
return candidates
|
|
205
|
+
rse_dump_urls.reverse()
|
|
193
206
|
success = False
|
|
194
207
|
while not success and len(rse_dump_urls):
|
|
195
208
|
url = rse_dump_urls.pop()
|
|
@@ -251,7 +264,12 @@ def _list_rebalance_rule_candidates_dump(rse_id, mode=None, logger=logging.log):
|
|
|
251
264
|
|
|
252
265
|
|
|
253
266
|
@transactional_session
|
|
254
|
-
def list_rebalance_rule_candidates(
|
|
267
|
+
def list_rebalance_rule_candidates(
|
|
268
|
+
rse_id: str,
|
|
269
|
+
mode: Optional[str] = None,
|
|
270
|
+
*,
|
|
271
|
+
session: Optional[Session] = None
|
|
272
|
+
) -> Union[list[tuple], list["Row[tuple]"]]:
|
|
255
273
|
"""
|
|
256
274
|
List the rebalance rule candidates based on the agreed on specification
|
|
257
275
|
:param rse_id: RSE of the source.
|
|
@@ -288,10 +306,8 @@ def list_rebalance_rule_candidates(rse_id, mode=None, *, session=None):
|
|
|
288
306
|
min_expires_date_in_days = datetime.utcnow() + timedelta(
|
|
289
307
|
days=min_expires_date_in_days
|
|
290
308
|
)
|
|
291
|
-
expiration_clause = or_(
|
|
292
|
-
|
|
293
|
-
models.ReplicationRule.expires_at.is_(None),
|
|
294
|
-
)
|
|
309
|
+
expiration_clause = or_(models.ReplicationRule.expires_at > min_expires_date_in_days,
|
|
310
|
+
models.ReplicationRule.expires_at.is_(None))
|
|
295
311
|
rule_clause.append(expiration_clause)
|
|
296
312
|
|
|
297
313
|
# Only move rules which were created more than <min_created_days> days ago
|
|
@@ -391,105 +407,89 @@ def list_rebalance_rule_candidates(rse_id, mode=None, *, session=None):
|
|
|
391
407
|
expiration_time=3600,
|
|
392
408
|
)
|
|
393
409
|
if only_move_closed_did:
|
|
394
|
-
did_clause.append(models.DataIdentifier.is_open ==
|
|
410
|
+
did_clause.append(models.DataIdentifier.is_open == false())
|
|
395
411
|
|
|
396
412
|
# Now build the query
|
|
397
413
|
external_dsl = aliased(models.DatasetLock)
|
|
398
|
-
count_locks = (
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
models.DatasetLock.length < 1,
|
|
422
|
-
models.DatasetLock.length.is_(None),
|
|
423
|
-
),
|
|
424
|
-
0,
|
|
425
|
-
),
|
|
426
|
-
else_=cast(
|
|
427
|
-
models.DatasetLock.bytes / models.DatasetLock.length, BigInteger
|
|
428
|
-
),
|
|
429
|
-
),
|
|
430
|
-
)
|
|
431
|
-
.join(
|
|
432
|
-
models.ReplicationRule,
|
|
433
|
-
models.ReplicationRule.id == models.DatasetLock.rule_id,
|
|
434
|
-
)
|
|
435
|
-
.join(
|
|
436
|
-
models.DataIdentifier,
|
|
437
|
-
and_(
|
|
438
|
-
models.DatasetLock.scope == models.DataIdentifier.scope,
|
|
439
|
-
models.DatasetLock.name == models.DataIdentifier.name,
|
|
414
|
+
count_locks = select(
|
|
415
|
+
func.count()
|
|
416
|
+
).select_from(
|
|
417
|
+
models.DatasetLock
|
|
418
|
+
).where(
|
|
419
|
+
and_(external_dsl.scope == models.DatasetLock.scope,
|
|
420
|
+
external_dsl.name == models.DatasetLock.name,
|
|
421
|
+
external_dsl.rse_id == models.DatasetLock.rse_id)
|
|
422
|
+
).scalar_subquery()
|
|
423
|
+
|
|
424
|
+
stmt = select(
|
|
425
|
+
models.DatasetLock.scope,
|
|
426
|
+
models.DatasetLock.name,
|
|
427
|
+
models.ReplicationRule.id,
|
|
428
|
+
models.ReplicationRule.rse_expression,
|
|
429
|
+
models.ReplicationRule.subscription_id,
|
|
430
|
+
models.DataIdentifier.bytes,
|
|
431
|
+
models.DataIdentifier.length,
|
|
432
|
+
case(
|
|
433
|
+
(
|
|
434
|
+
or_(models.DatasetLock.length < 1,
|
|
435
|
+
models.DatasetLock.length.is_(None)),
|
|
436
|
+
0
|
|
440
437
|
),
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
.filter(and_(*rule_clause))
|
|
444
|
-
.filter(and_(*did_clause))
|
|
445
|
-
.filter(
|
|
446
|
-
case(
|
|
447
|
-
(
|
|
448
|
-
or_(
|
|
449
|
-
models.DatasetLock.length < 1,
|
|
450
|
-
models.DatasetLock.length.is_(None),
|
|
451
|
-
),
|
|
452
|
-
0,
|
|
453
|
-
),
|
|
454
|
-
else_=cast(
|
|
455
|
-
models.DatasetLock.bytes / models.DatasetLock.length, BigInteger
|
|
456
|
-
),
|
|
438
|
+
else_=cast(
|
|
439
|
+
models.DatasetLock.bytes / models.DatasetLock.length, BigInteger
|
|
457
440
|
)
|
|
458
|
-
> 1000000000
|
|
459
441
|
)
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
442
|
+
).join(
|
|
443
|
+
models.ReplicationRule,
|
|
444
|
+
models.ReplicationRule.id == models.DatasetLock.rule_id
|
|
445
|
+
).join(
|
|
446
|
+
models.DataIdentifier,
|
|
447
|
+
and_(models.DatasetLock.scope == models.DataIdentifier.scope,
|
|
448
|
+
models.DatasetLock.name == models.DataIdentifier.name)
|
|
449
|
+
).where(
|
|
450
|
+
and_(models.DatasetLock.rse_id == rse_id,
|
|
451
|
+
*rule_clause,
|
|
452
|
+
*did_clause,
|
|
453
|
+
case(
|
|
454
|
+
(
|
|
455
|
+
or_(models.DatasetLock.length < 1,
|
|
456
|
+
models.DatasetLock.length.is_(None)),
|
|
457
|
+
0
|
|
458
|
+
),
|
|
459
|
+
else_=cast(
|
|
460
|
+
models.DatasetLock.bytes / models.DatasetLock.length, BigInteger
|
|
461
|
+
)
|
|
462
|
+
) > 1000000000,
|
|
463
|
+
count_locks == 1)
|
|
464
|
+
).order_by(
|
|
463
465
|
case(
|
|
464
466
|
(
|
|
465
|
-
or_(
|
|
466
|
-
models.DatasetLock.length
|
|
467
|
-
|
|
468
|
-
),
|
|
469
|
-
0,
|
|
467
|
+
or_(models.DatasetLock.length < 1,
|
|
468
|
+
models.DatasetLock.length.is_(None)),
|
|
469
|
+
0
|
|
470
470
|
),
|
|
471
471
|
else_=cast(
|
|
472
472
|
models.DatasetLock.bytes / models.DatasetLock.length, BigInteger
|
|
473
|
-
)
|
|
473
|
+
)
|
|
474
474
|
),
|
|
475
|
-
models.DatasetLock.accessed_at
|
|
476
|
-
)
|
|
477
|
-
return
|
|
475
|
+
models.DatasetLock.accessed_at
|
|
476
|
+
)
|
|
477
|
+
return list(session.execute(stmt).all()) # type: ignore (session could be None)
|
|
478
478
|
|
|
479
479
|
|
|
480
480
|
@read_session
|
|
481
481
|
def select_target_rse(
|
|
482
|
-
parent_rule,
|
|
483
|
-
current_rse_id,
|
|
484
|
-
rse_expression,
|
|
485
|
-
subscription_id,
|
|
486
|
-
rse_attributes,
|
|
487
|
-
other_rses
|
|
488
|
-
exclude_expression=None,
|
|
489
|
-
force_expression=None,
|
|
482
|
+
parent_rule: "Mapping[str, Any]",
|
|
483
|
+
current_rse_id: str,
|
|
484
|
+
rse_expression: str,
|
|
485
|
+
subscription_id: str,
|
|
486
|
+
rse_attributes: "Mapping[str, Any]",
|
|
487
|
+
other_rses: Optional["Sequence[str]"] = None,
|
|
488
|
+
exclude_expression: Optional[str] = None,
|
|
489
|
+
force_expression: Optional[str] = None,
|
|
490
490
|
*,
|
|
491
|
-
session=None,
|
|
492
|
-
):
|
|
491
|
+
session: Optional[Session] = None,
|
|
492
|
+
) -> str:
|
|
493
493
|
"""
|
|
494
494
|
Select a new target RSE for a rebalanced rule.
|
|
495
495
|
:param parent_rule rule that is rebalanced.
|
|
@@ -504,6 +504,7 @@ def select_target_rse(
|
|
|
504
504
|
:returns: New RSE expression.
|
|
505
505
|
"""
|
|
506
506
|
|
|
507
|
+
other_rses = other_rses or []
|
|
507
508
|
current_rse = get_rse_name(rse_id=current_rse_id)
|
|
508
509
|
current_rse_expr = current_rse
|
|
509
510
|
# if parent rule has a vo, enforce it
|
|
@@ -577,20 +578,20 @@ def select_target_rse(
|
|
|
577
578
|
|
|
578
579
|
@transactional_session
|
|
579
580
|
def rebalance_rse(
|
|
580
|
-
rse_id,
|
|
581
|
-
max_bytes=1e9,
|
|
582
|
-
max_files=None,
|
|
583
|
-
dry_run=False,
|
|
584
|
-
exclude_expression=None,
|
|
585
|
-
comment=None,
|
|
586
|
-
force_expression=None,
|
|
587
|
-
mode=None,
|
|
588
|
-
priority=3,
|
|
589
|
-
source_replica_expression="*\\bb8-enabled=false",
|
|
581
|
+
rse_id: str,
|
|
582
|
+
max_bytes: float = 1e9,
|
|
583
|
+
max_files: Optional[int] = None,
|
|
584
|
+
dry_run: bool = False,
|
|
585
|
+
exclude_expression: Optional[str] = None,
|
|
586
|
+
comment: Optional[str] = None,
|
|
587
|
+
force_expression: Optional[str] = None,
|
|
588
|
+
mode: Optional[str] = None,
|
|
589
|
+
priority: int = 3,
|
|
590
|
+
source_replica_expression: str = "*\\bb8-enabled=false",
|
|
590
591
|
*,
|
|
591
|
-
session=None,
|
|
592
|
-
logger=logging.log,
|
|
593
|
-
):
|
|
592
|
+
session: Optional[Session] = None,
|
|
593
|
+
logger: "LoggerFunction" = logging.log,
|
|
594
|
+
) -> list[tuple]:
|
|
594
595
|
"""
|
|
595
596
|
Rebalance data from an RSE
|
|
596
597
|
:param rse_id: RSE to rebalance data from.
|
|
@@ -705,7 +706,7 @@ def rebalance_rse(
|
|
|
705
706
|
except Exception as error:
|
|
706
707
|
logger(
|
|
707
708
|
logging.ERROR,
|
|
708
|
-
"Exception %s
|
|
709
|
+
"Exception %s occurred while rebalancing %s:%s, rule_id: %s!",
|
|
709
710
|
str(error),
|
|
710
711
|
scope,
|
|
711
712
|
name,
|
|
@@ -723,38 +724,34 @@ def rebalance_rse(
|
|
|
723
724
|
|
|
724
725
|
|
|
725
726
|
@read_session
|
|
726
|
-
def get_active_locks(
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
.all()
|
|
727
|
+
def get_active_locks(
|
|
728
|
+
*,
|
|
729
|
+
session: Optional[Session] = None
|
|
730
|
+
) -> dict[str, dict[str, int]]:
|
|
731
|
+
locks_dict: dict[str, dict[str, int]] = {}
|
|
732
|
+
stmt = select(
|
|
733
|
+
models.ReplicationRule.id
|
|
734
|
+
).where(
|
|
735
|
+
and_(or_(models.ReplicationRule.state == RuleState.REPLICATING,
|
|
736
|
+
models.ReplicationRule.state == RuleState.STUCK),
|
|
737
|
+
models.ReplicationRule.comments == "Background rebalancing")
|
|
738
738
|
)
|
|
739
|
-
for
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
.
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
)
|
|
754
|
-
.group_by(models.ReplicaLock.state, models.ReplicaLock.rse_id)
|
|
739
|
+
for rule_id in session.execute(stmt).scalars().all(): # type: ignore (session could be None)
|
|
740
|
+
stmt = select(
|
|
741
|
+
func.count(),
|
|
742
|
+
func.sum(models.ReplicaLock.bytes),
|
|
743
|
+
models.ReplicaLock.state,
|
|
744
|
+
models.ReplicaLock.rse_id
|
|
745
|
+
).select_from(
|
|
746
|
+
models.ReplicaLock
|
|
747
|
+
).where(
|
|
748
|
+
and_(models.ReplicaLock.rule_id == rule_id,
|
|
749
|
+
models.ReplicaLock.state != LockState.OK)
|
|
750
|
+
).group_by(
|
|
751
|
+
models.ReplicaLock.state,
|
|
752
|
+
models.ReplicaLock.rse_id
|
|
755
753
|
)
|
|
756
|
-
for
|
|
757
|
-
cnt, size, _, rse_id = lock
|
|
754
|
+
for cnt, size, _, rse_id in session.execute(stmt).all(): # type: ignore (session could be None)
|
|
758
755
|
if rse_id not in locks_dict:
|
|
759
756
|
locks_dict[rse_id] = {"bytes": 0, "locks": 0}
|
|
760
757
|
locks_dict[rse_id]["locks"] += cnt
|
|
@@ -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");
|
|
@@ -17,9 +16,10 @@
|
|
|
17
16
|
This script is to be used to background rebalance ATLAS t2 datadisks
|
|
18
17
|
"""
|
|
19
18
|
|
|
20
|
-
from sqlalchemy import or_
|
|
19
|
+
from sqlalchemy import and_, or_, select
|
|
21
20
|
|
|
22
|
-
from rucio.
|
|
21
|
+
from rucio.common.constants import RseAttr
|
|
22
|
+
from rucio.core.rse import get_rse_attribute, get_rse_usage
|
|
23
23
|
from rucio.core.rse_expression_parser import parse_expression
|
|
24
24
|
from rucio.daemons.bb8.common import rebalance_rse
|
|
25
25
|
from rucio.db.sqla import models
|
|
@@ -34,7 +34,7 @@ total_rebalance_volume = 0
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
# groupdisks
|
|
37
|
-
def group_space(site):
|
|
37
|
+
def group_space(site: str) -> int:
|
|
38
38
|
"""
|
|
39
39
|
groupdisks of given site
|
|
40
40
|
contributing to primaries
|
|
@@ -60,7 +60,7 @@ total_secondary = 0
|
|
|
60
60
|
total_total = 0
|
|
61
61
|
global_ratio = float(0)
|
|
62
62
|
for rse in rses:
|
|
63
|
-
site_name = get_rse_attribute(rse['id'],
|
|
63
|
+
site_name = get_rse_attribute(rse['id'], RseAttr.SITE)
|
|
64
64
|
rse['groupdisk'] = group_space(site_name)
|
|
65
65
|
rse['primary'] = get_rse_usage(rse_id=rse['id'], source='rucio')[0]['used'] - get_rse_usage(rse_id=rse['id'], source='expired')[0]['used']
|
|
66
66
|
rse['primary'] += rse['groupdisk']
|
|
@@ -81,12 +81,18 @@ rses_over_ratio = sorted([rse for rse in rses if rse['ratio'] > global_ratio + g
|
|
|
81
81
|
rses_under_ratio = sorted([rse for rse in rses if rse['ratio'] < global_ratio - global_ratio * tolerance], key=lambda k: k['ratio'], reverse=False)
|
|
82
82
|
|
|
83
83
|
session = get_session()
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
stmt = select(
|
|
85
|
+
models.ReplicationRule.rse_expression
|
|
86
|
+
).where(
|
|
87
|
+
and_(or_(models.ReplicationRule.state == RuleState.REPLICATING,
|
|
88
|
+
models.ReplicationRule.state == RuleState.STUCK),
|
|
89
|
+
models.ReplicationRule.comments == 'T2 Background rebalancing')
|
|
90
|
+
).group_by(
|
|
91
|
+
models.ReplicationRule.rse_expression
|
|
92
|
+
)
|
|
87
93
|
# Excluding RSEs
|
|
88
94
|
print('Excluding RSEs as destination which have active Background Rebalancing rules:')
|
|
89
|
-
for rse in
|
|
95
|
+
for rse in session.execute(stmt).all():
|
|
90
96
|
print(' %s' % (rse[0]))
|
|
91
97
|
for des in rses_under_ratio:
|
|
92
98
|
des_as_expr = des['rse']
|
|
@@ -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");
|
|
@@ -17,9 +16,10 @@
|
|
|
17
16
|
This script is to be used to background rebalance ATLAS t2 datadisks
|
|
18
17
|
"""
|
|
19
18
|
|
|
20
|
-
from sqlalchemy import or_
|
|
19
|
+
from sqlalchemy import and_, or_, select
|
|
21
20
|
|
|
22
|
-
from rucio.
|
|
21
|
+
from rucio.common.constants import RseAttr
|
|
22
|
+
from rucio.core.rse import get_rse_attribute, get_rse_usage
|
|
23
23
|
from rucio.core.rse_expression_parser import parse_expression
|
|
24
24
|
from rucio.daemons.bb8.common import rebalance_rse
|
|
25
25
|
from rucio.db.sqla import models
|
|
@@ -34,7 +34,7 @@ total_rebalance_volume = 0
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
# groupdisks
|
|
37
|
-
def group_space(site):
|
|
37
|
+
def group_space(site: str) -> int:
|
|
38
38
|
"""
|
|
39
39
|
groupdisks of given site
|
|
40
40
|
contributing to primaries
|
|
@@ -60,7 +60,7 @@ total_secondary = 0
|
|
|
60
60
|
total_total = 0
|
|
61
61
|
global_ratio = float(0)
|
|
62
62
|
for rse in rses:
|
|
63
|
-
site_name = get_rse_attribute(rse['id'],
|
|
63
|
+
site_name = get_rse_attribute(rse['id'], RseAttr.SITE)
|
|
64
64
|
rse['groupdisk'] = group_space(site_name)
|
|
65
65
|
rse['primary'] = get_rse_usage(rse_id=rse['id'], source='rucio')[0]['used'] - get_rse_usage(rse_id=rse['id'], source='expired')[0]['used']
|
|
66
66
|
rse['primary'] += rse['groupdisk']
|
|
@@ -81,12 +81,19 @@ rses_over_ratio = sorted([rse for rse in rses if rse['ratio'] > global_ratio + g
|
|
|
81
81
|
rses_under_ratio = sorted([rse for rse in rses if rse['ratio'] < global_ratio - global_ratio * tolerance], key=lambda k: k['ratio'], reverse=False)
|
|
82
82
|
|
|
83
83
|
session = get_session()
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
stmt = select(
|
|
85
|
+
models.ReplicationRule.rse_expression
|
|
86
|
+
).where(
|
|
87
|
+
and_(or_(models.ReplicationRule.state == RuleState.REPLICATING,
|
|
88
|
+
models.ReplicationRule.state == RuleState.STUCK),
|
|
89
|
+
models.ReplicationRule.comments == 'T2 Background rebalancing')
|
|
90
|
+
).group_by(
|
|
91
|
+
models.ReplicationRule.rse_expression
|
|
92
|
+
)
|
|
86
93
|
|
|
87
94
|
# Excluding RSEs
|
|
88
95
|
print('Excluding RSEs as destination which have active Background Rebalancing rules:')
|
|
89
|
-
for rse in
|
|
96
|
+
for rse in session.execute(stmt).all():
|
|
90
97
|
print(' %s' % (rse[0]))
|
|
91
98
|
for des in rses_under_ratio:
|
|
92
99
|
des_as_expr = des['rse']
|
rucio/daemons/c3po/__init__.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");
|
|
@@ -16,6 +15,7 @@
|
|
|
16
15
|
import logging
|
|
17
16
|
from operator import itemgetter
|
|
18
17
|
from random import shuffle
|
|
18
|
+
from typing import TYPE_CHECKING, Any
|
|
19
19
|
|
|
20
20
|
from rucio.common.exception import DataIdentifierNotFound
|
|
21
21
|
from rucio.core.did import get_did
|
|
@@ -24,6 +24,9 @@ from rucio.daemons.c3po.collectors.agis import MappingCollector
|
|
|
24
24
|
from rucio.daemons.c3po.collectors.workload import WorkloadCollector
|
|
25
25
|
from rucio.db.sqla.constants import ReplicaState
|
|
26
26
|
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from rucio.common.types import InternalScope
|
|
29
|
+
|
|
27
30
|
|
|
28
31
|
class PlacementAlgorithm:
|
|
29
32
|
def __init__(self):
|
|
@@ -31,20 +34,20 @@ class PlacementAlgorithm:
|
|
|
31
34
|
self._wc = WorkloadCollector()
|
|
32
35
|
self.__setup_penalties()
|
|
33
36
|
|
|
34
|
-
def __setup_penalties(self):
|
|
37
|
+
def __setup_penalties(self) -> None:
|
|
35
38
|
self._penalties = {}
|
|
36
39
|
for panda_site in self._wc.get_sites():
|
|
37
40
|
site = self._mc.panda_to_site(panda_site)
|
|
38
41
|
self._penalties[site] = 0.1
|
|
39
42
|
|
|
40
|
-
def __update_penalties(self):
|
|
43
|
+
def __update_penalties(self) -> None:
|
|
41
44
|
for site, penalty in self._penalties.items():
|
|
42
45
|
if penalty > 0.1:
|
|
43
46
|
self._penalties[site] = penalty - 0.1
|
|
44
47
|
|
|
45
|
-
def place(self, did):
|
|
48
|
+
def place(self, did: tuple['InternalScope', str]) -> dict[str, Any]:
|
|
46
49
|
self.__update_penalties()
|
|
47
|
-
decision = {'did': '{}:{}'.format(did['scope'].internal, did['name'])}
|
|
50
|
+
decision: dict[str, Any] = {'did': '{}:{}'.format(did['scope'].internal, did['name'])} # type: ignore (did is treated as a dict here, and as a tuple everywhere else)
|
|
48
51
|
try:
|
|
49
52
|
meta = get_did(did[0], did[1])
|
|
50
53
|
except DataIdentifierNotFound:
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -15,18 +14,22 @@
|
|
|
15
14
|
|
|
16
15
|
import logging
|
|
17
16
|
from operator import itemgetter
|
|
17
|
+
from typing import TYPE_CHECKING, Any
|
|
18
18
|
|
|
19
19
|
from rucio.common.config import config_get, config_get_int
|
|
20
20
|
from rucio.common.exception import DataIdentifierNotFound
|
|
21
21
|
from rucio.core.did import get_did
|
|
22
22
|
from rucio.core.replica import list_dataset_replicas
|
|
23
|
-
from rucio.core.rse import
|
|
23
|
+
from rucio.core.rse import get_rse_name, list_rse_attributes
|
|
24
24
|
from rucio.core.rse_expression_parser import parse_expression
|
|
25
25
|
from rucio.daemons.c3po.collectors.free_space import FreeSpaceCollector
|
|
26
26
|
from rucio.daemons.c3po.utils.dataset_cache import DatasetCache
|
|
27
27
|
from rucio.daemons.c3po.utils.popularity import get_popularity
|
|
28
28
|
from rucio.db.sqla.constants import ReplicaState
|
|
29
29
|
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from rucio.common.types import InternalScope
|
|
32
|
+
|
|
30
33
|
|
|
31
34
|
class PlacementAlgorithm:
|
|
32
35
|
"""
|
|
@@ -45,20 +48,20 @@ class PlacementAlgorithm:
|
|
|
45
48
|
|
|
46
49
|
self.__setup_penalties()
|
|
47
50
|
|
|
48
|
-
def __setup_penalties(self):
|
|
51
|
+
def __setup_penalties(self) -> None:
|
|
49
52
|
self._penalties = {}
|
|
50
53
|
for rse_id in self._rses:
|
|
51
54
|
self._penalties[rse_id] = 1.0
|
|
52
55
|
|
|
53
|
-
def __update_penalties(self):
|
|
56
|
+
def __update_penalties(self) -> None:
|
|
54
57
|
for rse_id, penalty in self._penalties.items():
|
|
55
58
|
if penalty > 1.0:
|
|
56
59
|
self._penalties[rse_id] = penalty - 1
|
|
57
60
|
|
|
58
|
-
def place(self, did):
|
|
61
|
+
def place(self, did: tuple['InternalScope', str]) -> dict[str, Any]:
|
|
59
62
|
self.__update_penalties()
|
|
60
|
-
decision = {'did': '{}:{}'.format(did[0].internal, did[1])}
|
|
61
|
-
if (not did[0].external.startswith('data')) and (not did[0].external.startswith('mc')):
|
|
63
|
+
decision: dict[str, Any] = {'did': '{}:{}'.format(did[0].internal, did[1])}
|
|
64
|
+
if (did[0].external is not None) and (not did[0].external.startswith('data')) and (not did[0].external.startswith('mc')):
|
|
62
65
|
decision['error_reason'] = 'not a data or mc dataset'
|
|
63
66
|
return decision
|
|
64
67
|
|