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
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -20,7 +19,7 @@ import re
|
|
|
20
19
|
from configparser import NoOptionError, NoSectionError
|
|
21
20
|
from functools import wraps
|
|
22
21
|
from time import time
|
|
23
|
-
from typing import TYPE_CHECKING
|
|
22
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, TypeVar, Union
|
|
24
23
|
|
|
25
24
|
import flask
|
|
26
25
|
from flask.views import MethodView
|
|
@@ -28,30 +27,36 @@ from werkzeug.datastructures import Headers
|
|
|
28
27
|
from werkzeug.exceptions import HTTPException
|
|
29
28
|
from werkzeug.wrappers import Request, Response
|
|
30
29
|
|
|
31
|
-
from rucio.api.authentication import validate_auth_token
|
|
32
30
|
from rucio.common import config
|
|
33
|
-
from rucio.common.exception import DatabaseException,
|
|
31
|
+
from rucio.common.exception import CannotAuthenticate, DatabaseException, IdentityError, RucioException, UnsupportedRequestedContentType
|
|
34
32
|
from rucio.common.schema import get_schema_value
|
|
35
33
|
from rucio.common.utils import generate_uuid, render_json
|
|
36
34
|
from rucio.core.vo import map_vo
|
|
35
|
+
from rucio.gateway.authentication import validate_auth_token
|
|
36
|
+
from rucio.gateway.identity import get_default_account, list_accounts_for_identity, verify_identity
|
|
37
37
|
|
|
38
38
|
if TYPE_CHECKING:
|
|
39
|
-
from collections.abc import Callable, Iterable
|
|
40
|
-
from typing import Optional, Union, Any
|
|
39
|
+
from collections.abc import Callable, Iterable
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
from _typeshed import SupportsIter
|
|
42
|
+
from _typeshed.wsgi import StartResponse, WSGIApplication, WSGIEnvironment
|
|
43
|
+
from flask.typing import ResponseReturnValue
|
|
43
44
|
|
|
45
|
+
from rucio.web.rest.flaskapi.v1.types import HeadersType
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
ResponseTypeVar = TypeVar('ResponseTypeVar', bound=flask.wrappers.Response)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class CORSMiddleware:
|
|
46
51
|
"""
|
|
47
52
|
WebUI 2.0 makes preflight requests to the API, which are not handled by the API.
|
|
48
53
|
This middleware intercepts the preflight OPTIONS requests and returns a 200 OK response.
|
|
49
54
|
"""
|
|
50
55
|
|
|
51
|
-
def __init__(self, app:
|
|
56
|
+
def __init__(self, app: 'WSGIApplication') -> None:
|
|
52
57
|
self.app = app
|
|
53
58
|
|
|
54
|
-
def __call__(self, environ:
|
|
59
|
+
def __call__(self, environ: 'WSGIEnvironment', start_response: 'StartResponse') -> 'Iterable[bytes]':
|
|
55
60
|
request: Request = Request(environ)
|
|
56
61
|
|
|
57
62
|
if request.environ.get('REQUEST_METHOD') == 'OPTIONS':
|
|
@@ -59,12 +64,12 @@ class CORSMiddleware(object):
|
|
|
59
64
|
webui_urls = config.config_get_list('webui', 'urls')
|
|
60
65
|
except (NoOptionError, NoSectionError, RuntimeError) as error:
|
|
61
66
|
logging.exception('Could not get webui urls from config file')
|
|
62
|
-
return str(error), 500
|
|
67
|
+
return str(error), 500 # type: ignore (return type incompatible with Flask middleware)
|
|
63
68
|
if request.origin in webui_urls:
|
|
64
69
|
response: Response = Response(status=200)
|
|
65
70
|
response.headers['Access-Control-Allow-Origin'] = request.origin
|
|
66
71
|
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
|
|
67
|
-
response.headers['Access-Control-Allow-Headers'] = '
|
|
72
|
+
response.headers['Access-Control-Allow-Headers'] = request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') # type: ignore (value could be None)
|
|
68
73
|
response.headers['Access-Control-Allow-Credentials'] = 'true'
|
|
69
74
|
return response(environ, start_response)
|
|
70
75
|
response: Response = Response(status=403)
|
|
@@ -80,11 +85,11 @@ class ErrorHandlingMethodView(MethodView):
|
|
|
80
85
|
Exceptions for all defined methods automatically.
|
|
81
86
|
"""
|
|
82
87
|
|
|
83
|
-
def get_headers(self) ->
|
|
88
|
+
def get_headers(self) -> Optional['HeadersType']:
|
|
84
89
|
"""Can be overridden to add headers to generic error responses."""
|
|
85
90
|
return None
|
|
86
91
|
|
|
87
|
-
def dispatch_request(self, *args, **kwargs):
|
|
92
|
+
def dispatch_request(self, *args, **kwargs) -> Union['ResponseReturnValue', flask.wrappers.Response]:
|
|
88
93
|
headers = self.get_headers() or None
|
|
89
94
|
try:
|
|
90
95
|
return super(ErrorHandlingMethodView, self).dispatch_request(*args, **kwargs)
|
|
@@ -108,7 +113,7 @@ class ErrorHandlingMethodView(MethodView):
|
|
|
108
113
|
return generate_http_error_flask(
|
|
109
114
|
status_code=500,
|
|
110
115
|
exc=error.__class__.__name__,
|
|
111
|
-
exc_msg='An unknown Database Exception has
|
|
116
|
+
exc_msg='An unknown Database Exception has occurred.',
|
|
112
117
|
headers=headers
|
|
113
118
|
)
|
|
114
119
|
|
|
@@ -132,7 +137,7 @@ class ErrorHandlingMethodView(MethodView):
|
|
|
132
137
|
return str(error), 500
|
|
133
138
|
|
|
134
139
|
|
|
135
|
-
def request_auth_env():
|
|
140
|
+
def request_auth_env() -> Optional['ResponseReturnValue']:
|
|
136
141
|
if flask.request.environ.get('REQUEST_METHOD') == 'OPTIONS':
|
|
137
142
|
return '', 200
|
|
138
143
|
|
|
@@ -155,9 +160,9 @@ def request_auth_env():
|
|
|
155
160
|
flask.request.environ['start_time'] = time()
|
|
156
161
|
|
|
157
162
|
|
|
158
|
-
def response_headers(response):
|
|
159
|
-
response.headers['Access-Control-Allow-Origin'] = flask.request.environ.get('HTTP_ORIGIN')
|
|
160
|
-
response.headers['Access-Control-Allow-Headers'] = flask.request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')
|
|
163
|
+
def response_headers(response: ResponseTypeVar) -> ResponseTypeVar:
|
|
164
|
+
response.headers['Access-Control-Allow-Origin'] = flask.request.environ.get('HTTP_ORIGIN') # type: ignore (value could be None)
|
|
165
|
+
response.headers['Access-Control-Allow-Headers'] = flask.request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') # type: ignore (value could be None)
|
|
161
166
|
response.headers['Access-Control-Allow-Methods'] = '*'
|
|
162
167
|
response.headers['Access-Control-Allow-Credentials'] = 'true'
|
|
163
168
|
|
|
@@ -169,7 +174,7 @@ def response_headers(response):
|
|
|
169
174
|
return response
|
|
170
175
|
|
|
171
176
|
|
|
172
|
-
def check_accept_header_wrapper_flask(supported_content_types):
|
|
177
|
+
def check_accept_header_wrapper_flask(supported_content_types: 'Iterable[str]'):
|
|
173
178
|
""" Decorator to check if an endpoint supports the requested content type. """
|
|
174
179
|
|
|
175
180
|
def wrapper(f):
|
|
@@ -195,7 +200,7 @@ def check_accept_header_wrapper_flask(supported_content_types):
|
|
|
195
200
|
return wrapper
|
|
196
201
|
|
|
197
202
|
|
|
198
|
-
def parse_scope_name(scope_name, vo):
|
|
203
|
+
def parse_scope_name(scope_name: str, vo: Optional[str]) -> tuple[str, ...]:
|
|
199
204
|
"""
|
|
200
205
|
Parses the given scope_name according to the schema's
|
|
201
206
|
SCOPE_NAME_REGEXP and returns a (scope, name) tuple.
|
|
@@ -205,14 +210,20 @@ def parse_scope_name(scope_name, vo):
|
|
|
205
210
|
:raises ValueError: when scope_name could not be parsed.
|
|
206
211
|
:returns: a (scope, name) tuple.
|
|
207
212
|
"""
|
|
213
|
+
if not vo:
|
|
214
|
+
vo = 'def'
|
|
215
|
+
|
|
208
216
|
# why again does that regex start with a slash?
|
|
209
|
-
|
|
210
|
-
if
|
|
217
|
+
scope_regex = re.match(get_schema_value('SCOPE_NAME_REGEXP', vo), '/' + scope_name)
|
|
218
|
+
if scope_regex is None:
|
|
211
219
|
raise ValueError('cannot parse scope and name')
|
|
212
|
-
return
|
|
220
|
+
return scope_regex.group(1, 2)
|
|
213
221
|
|
|
214
222
|
|
|
215
|
-
def try_stream(
|
|
223
|
+
def try_stream(
|
|
224
|
+
generator: 'SupportsIter',
|
|
225
|
+
content_type: Optional[str] = None
|
|
226
|
+
) -> flask.Response:
|
|
216
227
|
"""
|
|
217
228
|
Peeks at the first element of the passed generator and raises
|
|
218
229
|
an error, if yielding raises. Otherwise returns
|
|
@@ -234,15 +245,12 @@ def try_stream(generator, content_type=None) -> "flask.Response":
|
|
|
234
245
|
return flask.Response('', content_type=content_type)
|
|
235
246
|
|
|
236
247
|
|
|
237
|
-
def error_headers(exc_cls: str, exc_msg):
|
|
238
|
-
def strip_newlines(msg):
|
|
239
|
-
if msg is None:
|
|
240
|
-
return None
|
|
241
|
-
|
|
248
|
+
def error_headers(exc_cls: str, exc_msg: str) -> dict[str, str]:
|
|
249
|
+
def strip_newlines(msg: str) -> str:
|
|
242
250
|
return msg.replace('\n', ' ').replace('\r', ' ')
|
|
243
251
|
|
|
244
|
-
exc_msg = strip_newlines(exc_msg)
|
|
245
252
|
if exc_msg:
|
|
253
|
+
exc_msg = strip_newlines(exc_msg)
|
|
246
254
|
# Truncate too long exc_msg
|
|
247
255
|
oldlen = len(exc_msg)
|
|
248
256
|
exc_msg = exc_msg[:min(oldlen, 125)]
|
|
@@ -254,7 +262,7 @@ def error_headers(exc_cls: str, exc_msg):
|
|
|
254
262
|
}
|
|
255
263
|
|
|
256
264
|
|
|
257
|
-
def _error_response(exc_cls, exc_msg):
|
|
265
|
+
def _error_response(exc_cls: str, exc_msg: str) -> tuple[dict[str, str], dict[str, str]]:
|
|
258
266
|
data = {'ExceptionClass': exc_cls,
|
|
259
267
|
'ExceptionMessage': exc_msg}
|
|
260
268
|
headers = {'Content-Type': 'application/octet-stream'}
|
|
@@ -263,12 +271,12 @@ def _error_response(exc_cls, exc_msg):
|
|
|
263
271
|
|
|
264
272
|
|
|
265
273
|
def generate_http_error_flask(
|
|
266
|
-
status_code:
|
|
267
|
-
exc:
|
|
268
|
-
exc_msg:
|
|
269
|
-
headers:
|
|
274
|
+
status_code: int,
|
|
275
|
+
exc: Union[str, BaseException],
|
|
276
|
+
exc_msg: Optional[str] = None,
|
|
277
|
+
headers: Optional['HeadersType'] = None,
|
|
270
278
|
) -> "flask.Response":
|
|
271
|
-
"""
|
|
279
|
+
"""Utility function to generate a complete HTTP error response.
|
|
272
280
|
|
|
273
281
|
:param status_code: The HTTP status code to generate a response for.
|
|
274
282
|
:param exc: The name of the exception class or a RucioException object.
|
|
@@ -322,13 +330,13 @@ def json_list(json_loads: "Callable[[str], Any]" = json.loads, optional: bool =
|
|
|
322
330
|
|
|
323
331
|
|
|
324
332
|
def json_parse(types: tuple, json_loads: "Callable[[str], Any]" = json.loads, **kwargs):
|
|
325
|
-
def clstostr(cls):
|
|
333
|
+
def clstostr(cls) -> str:
|
|
326
334
|
if cls.__name__ == "dict":
|
|
327
335
|
return "dictionary"
|
|
328
336
|
else:
|
|
329
337
|
return cls.__name__
|
|
330
338
|
|
|
331
|
-
def typestostr(_types: tuple):
|
|
339
|
+
def typestostr(_types: tuple) -> str:
|
|
332
340
|
return " or ".join(map(clstostr, _types))
|
|
333
341
|
|
|
334
342
|
data = flask.request.get_data(as_text=True)
|
|
@@ -355,7 +363,7 @@ def json_parse(types: tuple, json_loads: "Callable[[str], Any]" = json.loads, **
|
|
|
355
363
|
)
|
|
356
364
|
|
|
357
365
|
|
|
358
|
-
def param_get(parameters: dict, name: str, **kwargs):
|
|
366
|
+
def param_get(parameters: dict[str, Any], name: str, **kwargs) -> Any:
|
|
359
367
|
if 'default' in kwargs:
|
|
360
368
|
return parameters.get(name, kwargs['default'])
|
|
361
369
|
else:
|
|
@@ -370,7 +378,7 @@ def param_get(parameters: dict, name: str, **kwargs):
|
|
|
370
378
|
return parameters[name]
|
|
371
379
|
|
|
372
380
|
|
|
373
|
-
def extract_vo(headers:
|
|
381
|
+
def extract_vo(headers: Headers) -> str:
|
|
374
382
|
""" Extract the VO name from the given request.headers object and
|
|
375
383
|
does any name mapping. Returns the short VO name or raise a
|
|
376
384
|
flask.abort if the VO name doesn't meet the name specification.
|
|
@@ -383,3 +391,36 @@ def extract_vo(headers: "HeadersType") -> "str":
|
|
|
383
391
|
except RucioException as err:
|
|
384
392
|
# VO Name doesn't match allowed spec
|
|
385
393
|
flask.abort(generate_http_error_flask(status_code=400, exc=err))
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def get_account_from_verified_identity(
|
|
397
|
+
identity_key: str,
|
|
398
|
+
id_type: Literal["USERPASS", "X509"],
|
|
399
|
+
password: Optional[str] = None
|
|
400
|
+
) -> list[str]:
|
|
401
|
+
""" Verifies the provided identity and tries to return a matching account.
|
|
402
|
+
If no account is found, raises an IdentityError after trying to verify the identity.
|
|
403
|
+
If multiple accounts are found, returns the default account if available, otherwise all accounts.
|
|
404
|
+
:param identity_key: The identity key name. For example x509 DN, or a username.
|
|
405
|
+
:param id_type: The type of the authentication (x509, USERPASS).
|
|
406
|
+
:param password: required only if id_type==USERPASS.
|
|
407
|
+
:raises IdentityError: if no account is found for the identity or if the identity could not be verified.
|
|
408
|
+
:returns: a list of account names.
|
|
409
|
+
"""
|
|
410
|
+
accounts = list_accounts_for_identity(identity_key=identity_key, id_type=id_type)
|
|
411
|
+
if accounts is None or len(accounts) == 0:
|
|
412
|
+
if id_type == 'USERPASS':
|
|
413
|
+
verify_identity(identity_key=identity_key, id_type=id_type, password=password)
|
|
414
|
+
elif id_type == 'X509':
|
|
415
|
+
verify_identity(identity_key=identity_key, id_type=id_type)
|
|
416
|
+
else:
|
|
417
|
+
raise IdentityError('No account found for identity')
|
|
418
|
+
if len(accounts) > 1:
|
|
419
|
+
try:
|
|
420
|
+
default_account = get_default_account(identity_key=identity_key, id_type=id_type)
|
|
421
|
+
return [default_account]
|
|
422
|
+
except IdentityError:
|
|
423
|
+
return accounts
|
|
424
|
+
else:
|
|
425
|
+
account = accounts[0]
|
|
426
|
+
return [account]
|
|
@@ -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");
|
|
@@ -13,13 +12,13 @@
|
|
|
13
12
|
# See the License for the specific language governing permissions and
|
|
14
13
|
# limitations under the License.
|
|
15
14
|
|
|
16
|
-
from flask import Flask,
|
|
15
|
+
from flask import Flask, jsonify
|
|
16
|
+
from flask import request as request
|
|
17
17
|
|
|
18
|
-
from rucio.
|
|
19
|
-
from rucio.
|
|
18
|
+
from rucio.common.exception import AccessDenied, ConfigNotFound, ConfigurationError
|
|
19
|
+
from rucio.gateway import config
|
|
20
20
|
from rucio.web.rest.flaskapi.authenticated_bp import AuthenticatedBlueprint
|
|
21
|
-
from rucio.web.rest.flaskapi.v1.common import
|
|
22
|
-
generate_http_error_flask, ErrorHandlingMethodView, json_parameters
|
|
21
|
+
from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, check_accept_header_wrapper_flask, generate_http_error_flask, json_parameters, response_headers
|
|
23
22
|
|
|
24
23
|
|
|
25
24
|
class Config(ErrorHandlingMethodView):
|
|
@@ -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");
|
|
@@ -18,15 +17,15 @@ from typing import TYPE_CHECKING
|
|
|
18
17
|
from flask import Flask, request
|
|
19
18
|
from werkzeug.datastructures import Headers
|
|
20
19
|
|
|
21
|
-
from rucio.api.credential import get_signed_url
|
|
22
20
|
from rucio.common.exception import CannotAuthenticate
|
|
21
|
+
from rucio.gateway.credential import get_signed_url
|
|
23
22
|
from rucio.web.rest.flaskapi.authenticated_bp import AuthenticatedBlueprint
|
|
24
|
-
from rucio.web.rest.flaskapi.v1.common import check_accept_header_wrapper_flask, extract_vo,
|
|
25
|
-
generate_http_error_flask, ErrorHandlingMethodView, response_headers
|
|
23
|
+
from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, check_accept_header_wrapper_flask, extract_vo, generate_http_error_flask, response_headers
|
|
26
24
|
|
|
27
25
|
if TYPE_CHECKING:
|
|
28
26
|
from typing import Optional
|
|
29
|
-
|
|
27
|
+
|
|
28
|
+
from rucio.web.rest.flaskapi.v1.types import HeadersType
|
|
30
29
|
|
|
31
30
|
|
|
32
31
|
class SignURL(ErrorHandlingMethodView):
|
|
@@ -61,7 +60,7 @@ class SignURL(ErrorHandlingMethodView):
|
|
|
61
60
|
Access-Control-Allow-Headers:
|
|
62
61
|
schema:
|
|
63
62
|
type: string
|
|
64
|
-
description: The http access
|
|
63
|
+
description: The http access control request headers.
|
|
65
64
|
Access-Control-Allow-Methods:
|
|
66
65
|
schema:
|
|
67
66
|
type: string
|
|
@@ -76,7 +75,7 @@ class SignURL(ErrorHandlingMethodView):
|
|
|
76
75
|
schema:
|
|
77
76
|
type: string
|
|
78
77
|
enum: ['X-Rucio-Auth-Token']
|
|
79
|
-
description: The exposed access
|
|
78
|
+
description: The exposed access control header.
|
|
80
79
|
404:
|
|
81
80
|
description: Not found
|
|
82
81
|
"""
|
|
@@ -117,7 +116,7 @@ class SignURL(ErrorHandlingMethodView):
|
|
|
117
116
|
required: false
|
|
118
117
|
- name: url
|
|
119
118
|
in: query
|
|
120
|
-
description: The Url of the
|
|
119
|
+
description: The Url of the authentication.
|
|
121
120
|
schema:
|
|
122
121
|
type: string
|
|
123
122
|
required: true
|
|
@@ -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");
|
|
@@ -18,20 +17,61 @@ from json import dumps
|
|
|
18
17
|
|
|
19
18
|
from flask import Flask, Response, request
|
|
20
19
|
|
|
21
|
-
from rucio.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
20
|
+
from rucio.common.exception import (
|
|
21
|
+
AccessDenied,
|
|
22
|
+
DatabaseException,
|
|
23
|
+
DataIdentifierAlreadyExists,
|
|
24
|
+
DataIdentifierNotFound,
|
|
25
|
+
Duplicate,
|
|
26
|
+
DuplicateContent,
|
|
27
|
+
FileAlreadyExists,
|
|
28
|
+
FileConsistencyMismatch,
|
|
29
|
+
InvalidMetadata,
|
|
30
|
+
InvalidObject,
|
|
31
|
+
InvalidPath,
|
|
32
|
+
InvalidValueForKey,
|
|
33
|
+
KeyNotFound,
|
|
34
|
+
RSENotFound,
|
|
35
|
+
RuleNotFound,
|
|
36
|
+
ScopeNotFound,
|
|
37
|
+
UnsupportedMetadataPlugin,
|
|
38
|
+
UnsupportedOperation,
|
|
39
|
+
UnsupportedStatus,
|
|
40
|
+
)
|
|
41
|
+
from rucio.common.utils import APIEncoder, parse_response, render_json
|
|
31
42
|
from rucio.db.sqla.constants import DIDType
|
|
43
|
+
from rucio.gateway.did import (
|
|
44
|
+
add_did,
|
|
45
|
+
add_did_to_followed,
|
|
46
|
+
add_dids,
|
|
47
|
+
attach_dids,
|
|
48
|
+
attach_dids_to_dids,
|
|
49
|
+
bulk_list_files,
|
|
50
|
+
create_did_sample,
|
|
51
|
+
delete_metadata,
|
|
52
|
+
detach_dids,
|
|
53
|
+
get_dataset_by_guid,
|
|
54
|
+
get_did,
|
|
55
|
+
get_metadata,
|
|
56
|
+
get_metadata_bulk,
|
|
57
|
+
get_users_following_did,
|
|
58
|
+
list_content,
|
|
59
|
+
list_content_history,
|
|
60
|
+
list_dids,
|
|
61
|
+
list_files,
|
|
62
|
+
list_new_dids,
|
|
63
|
+
list_parent_dids,
|
|
64
|
+
remove_did_from_followed,
|
|
65
|
+
resurrect,
|
|
66
|
+
scope_list,
|
|
67
|
+
set_dids_metadata_bulk,
|
|
68
|
+
set_metadata,
|
|
69
|
+
set_metadata_bulk,
|
|
70
|
+
set_status,
|
|
71
|
+
)
|
|
72
|
+
from rucio.gateway.rule import list_associated_replication_rules_for_file, list_replication_rules
|
|
32
73
|
from rucio.web.rest.flaskapi.authenticated_bp import AuthenticatedBlueprint
|
|
33
|
-
from rucio.web.rest.flaskapi.v1.common import
|
|
34
|
-
parse_scope_name, try_stream, generate_http_error_flask, ErrorHandlingMethodView, json_parameters, json_list, param_get, json_parse
|
|
74
|
+
from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, check_accept_header_wrapper_flask, generate_http_error_flask, json_list, json_parameters, json_parse, param_get, parse_scope_name, response_headers, try_stream
|
|
35
75
|
|
|
36
76
|
|
|
37
77
|
class Scope(ErrorHandlingMethodView):
|
|
@@ -69,7 +109,7 @@ class Scope(ErrorHandlingMethodView):
|
|
|
69
109
|
content:
|
|
70
110
|
application/x-json-stream:
|
|
71
111
|
schema:
|
|
72
|
-
description: Line
|
|
112
|
+
description: Line separated dictionary of dids.
|
|
73
113
|
type: array
|
|
74
114
|
items:
|
|
75
115
|
type: object
|
|
@@ -220,7 +260,7 @@ class Search(ErrorHandlingMethodView):
|
|
|
220
260
|
if filters is not None:
|
|
221
261
|
filters = ast.literal_eval(filters)
|
|
222
262
|
else:
|
|
223
|
-
# backwards
|
|
263
|
+
# backwards compatibility for created*, length* and name filters passed through as request args
|
|
224
264
|
filters = {}
|
|
225
265
|
for arg, value in request.args.copy().items():
|
|
226
266
|
if arg not in ['type', 'limit', 'long', 'recursive']:
|
|
@@ -414,10 +454,11 @@ class Attachments(ErrorHandlingMethodView):
|
|
|
414
454
|
if isinstance(parameters, list):
|
|
415
455
|
attachments = parameters
|
|
416
456
|
ignore_duplicate = False
|
|
417
|
-
|
|
418
|
-
assert isinstance(parameters, dict)
|
|
457
|
+
elif isinstance(parameters, dict):
|
|
419
458
|
attachments = param_get(parameters, 'attachments')
|
|
420
459
|
ignore_duplicate = param_get(parameters, 'ignore_duplicate', default=False)
|
|
460
|
+
else:
|
|
461
|
+
return generate_http_error_flask(406, exc="Invalid attachment format.")
|
|
421
462
|
|
|
422
463
|
try:
|
|
423
464
|
attach_dids_to_dids(attachments=attachments, ignore_duplicate=ignore_duplicate, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'))
|
|
@@ -742,7 +783,7 @@ class Attachment(ErrorHandlingMethodView):
|
|
|
742
783
|
content:
|
|
743
784
|
application/x-json-stream:
|
|
744
785
|
schema:
|
|
745
|
-
description: The contents of a did. Items are line
|
|
786
|
+
description: The contents of a did. Items are line separated.
|
|
746
787
|
type: array
|
|
747
788
|
items:
|
|
748
789
|
type: object
|
|
@@ -955,7 +996,7 @@ class AttachmentHistory(ErrorHandlingMethodView):
|
|
|
955
996
|
content:
|
|
956
997
|
application/x-json-stream:
|
|
957
998
|
schema:
|
|
958
|
-
description: The dids with their information and history. Elements are
|
|
999
|
+
description: The dids with their information and history. Elements are separated by new line characters.
|
|
959
1000
|
type: array
|
|
960
1001
|
items:
|
|
961
1002
|
type: object
|
|
@@ -1063,7 +1104,7 @@ class Files(ErrorHandlingMethodView):
|
|
|
1063
1104
|
description: The adler32 checksum.
|
|
1064
1105
|
type: string
|
|
1065
1106
|
lumiblocknr:
|
|
1066
|
-
description: The lumi block nr. Only
|
|
1107
|
+
description: The lumi block nr. Only available if `long` is defined in the query.
|
|
1067
1108
|
type: integer
|
|
1068
1109
|
- description: All replica information.
|
|
1069
1110
|
type: array
|
|
@@ -1111,6 +1152,86 @@ class Files(ErrorHandlingMethodView):
|
|
|
1111
1152
|
return generate_http_error_flask(404, error)
|
|
1112
1153
|
|
|
1113
1154
|
|
|
1155
|
+
class BulkFiles(ErrorHandlingMethodView):
|
|
1156
|
+
|
|
1157
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
1158
|
+
def post(self):
|
|
1159
|
+
"""
|
|
1160
|
+
---
|
|
1161
|
+
summary: List files bulk
|
|
1162
|
+
description: List files in multiple dids
|
|
1163
|
+
tags:
|
|
1164
|
+
- Data Identifiers
|
|
1165
|
+
requestBody:
|
|
1166
|
+
content:
|
|
1167
|
+
application/json:
|
|
1168
|
+
schema:
|
|
1169
|
+
type: array
|
|
1170
|
+
items:
|
|
1171
|
+
description: One did to list files.
|
|
1172
|
+
type: object
|
|
1173
|
+
required:
|
|
1174
|
+
- scope
|
|
1175
|
+
- name
|
|
1176
|
+
properties:
|
|
1177
|
+
scope:
|
|
1178
|
+
description: The did scope.
|
|
1179
|
+
type: string
|
|
1180
|
+
name:
|
|
1181
|
+
description: The did name.
|
|
1182
|
+
type: string
|
|
1183
|
+
responses:
|
|
1184
|
+
201:
|
|
1185
|
+
description: OK
|
|
1186
|
+
content:
|
|
1187
|
+
application/x-json-stream:
|
|
1188
|
+
schema:
|
|
1189
|
+
description: All collections file content.
|
|
1190
|
+
type: array
|
|
1191
|
+
items:
|
|
1192
|
+
description: Collections file content.
|
|
1193
|
+
type: object
|
|
1194
|
+
properties:
|
|
1195
|
+
parent_scope:
|
|
1196
|
+
description: The scope of the parent did.
|
|
1197
|
+
type: string
|
|
1198
|
+
parent_name:
|
|
1199
|
+
description: The name of the parent did.
|
|
1200
|
+
type: string
|
|
1201
|
+
scope:
|
|
1202
|
+
description: The scope of the did.
|
|
1203
|
+
type: string
|
|
1204
|
+
name:
|
|
1205
|
+
description: The name of the did.
|
|
1206
|
+
type: string
|
|
1207
|
+
bytes:
|
|
1208
|
+
description: The size of the did in bytes.
|
|
1209
|
+
type: integer
|
|
1210
|
+
guid:
|
|
1211
|
+
description: The guid of the did.
|
|
1212
|
+
type: string
|
|
1213
|
+
events:
|
|
1214
|
+
description: The number of events of the did.
|
|
1215
|
+
type: integer
|
|
1216
|
+
adler32:
|
|
1217
|
+
description: The adler32 checksum.
|
|
1218
|
+
type: string
|
|
1219
|
+
401:
|
|
1220
|
+
description: Invalid Auth Token
|
|
1221
|
+
"""
|
|
1222
|
+
parameters = json_parameters(parse_response)
|
|
1223
|
+
dids = param_get(parameters, 'dids', default=[])
|
|
1224
|
+
try:
|
|
1225
|
+
def generate(vo):
|
|
1226
|
+
for did in bulk_list_files(dids=dids, vo=vo):
|
|
1227
|
+
yield render_json(**did) + '\n'
|
|
1228
|
+
|
|
1229
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
1230
|
+
except AccessDenied as error:
|
|
1231
|
+
return generate_http_error_flask(401, error)
|
|
1232
|
+
return 'Created', 201
|
|
1233
|
+
|
|
1234
|
+
|
|
1114
1235
|
class Parents(ErrorHandlingMethodView):
|
|
1115
1236
|
|
|
1116
1237
|
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
@@ -1199,8 +1320,10 @@ class Meta(ErrorHandlingMethodView):
|
|
|
1199
1320
|
content:
|
|
1200
1321
|
application/json:
|
|
1201
1322
|
schema:
|
|
1202
|
-
description: A data
|
|
1323
|
+
description: A data identifier with all attributes.
|
|
1203
1324
|
type: object
|
|
1325
|
+
400:
|
|
1326
|
+
description: Bad Request - Invalid metadata plugin specified
|
|
1204
1327
|
401:
|
|
1205
1328
|
description: Invalid Auth Token
|
|
1206
1329
|
404:
|
|
@@ -1219,6 +1342,8 @@ class Meta(ErrorHandlingMethodView):
|
|
|
1219
1342
|
return Response(render_json(**meta), content_type='application/json')
|
|
1220
1343
|
except DataIdentifierNotFound as error:
|
|
1221
1344
|
return generate_http_error_flask(404, error)
|
|
1345
|
+
except UnsupportedMetadataPlugin as error:
|
|
1346
|
+
return generate_http_error_flask(400, error)
|
|
1222
1347
|
|
|
1223
1348
|
def post(self, scope_name):
|
|
1224
1349
|
"""
|
|
@@ -1243,7 +1368,7 @@ class Meta(ErrorHandlingMethodView):
|
|
|
1243
1368
|
- meta
|
|
1244
1369
|
properties:
|
|
1245
1370
|
meta:
|
|
1246
|
-
description: The metadata to add. A dictionary
|
|
1371
|
+
description: The metadata to add. A dictionary containing the metadata name as key and the value as value.
|
|
1247
1372
|
type: object
|
|
1248
1373
|
recursive:
|
|
1249
1374
|
description: Flag if the metadata should be applied recirsively to children.
|
|
@@ -1390,7 +1515,7 @@ class SingleMeta(ErrorHandlingMethodView):
|
|
|
1390
1515
|
406:
|
|
1391
1516
|
description: Not acceptable
|
|
1392
1517
|
409:
|
|
1393
|
-
description:
|
|
1518
|
+
description: Metadata already exists
|
|
1394
1519
|
400:
|
|
1395
1520
|
description: Invalid key or value
|
|
1396
1521
|
"""
|
|
@@ -1526,6 +1651,7 @@ class Rules(ErrorHandlingMethodView):
|
|
|
1526
1651
|
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1527
1652
|
|
|
1528
1653
|
def generate(vo):
|
|
1654
|
+
get_did(scope=scope, name=name, vo=vo)
|
|
1529
1655
|
for rule in list_replication_rules({'scope': scope, 'name': name}, vo=vo):
|
|
1530
1656
|
yield dumps(rule, cls=APIEncoder) + '\n'
|
|
1531
1657
|
|
|
@@ -1534,6 +1660,8 @@ class Rules(ErrorHandlingMethodView):
|
|
|
1534
1660
|
return generate_http_error_flask(400, error)
|
|
1535
1661
|
except RuleNotFound as error:
|
|
1536
1662
|
return generate_http_error_flask(404, error)
|
|
1663
|
+
except DataIdentifierNotFound as error:
|
|
1664
|
+
return generate_http_error_flask(404, error)
|
|
1537
1665
|
|
|
1538
1666
|
|
|
1539
1667
|
class BulkMeta(ErrorHandlingMethodView):
|
|
@@ -1577,7 +1705,7 @@ class BulkMeta(ErrorHandlingMethodView):
|
|
|
1577
1705
|
content:
|
|
1578
1706
|
application/json:
|
|
1579
1707
|
schema:
|
|
1580
|
-
description: A list of metadata identifiers for the dids.
|
|
1708
|
+
description: A list of metadata identifiers for the dids. Separated by new lines.
|
|
1581
1709
|
type: array
|
|
1582
1710
|
items:
|
|
1583
1711
|
description: The metadata for one did.
|
|
@@ -1613,7 +1741,7 @@ class AssociatedRules(ErrorHandlingMethodView):
|
|
|
1613
1741
|
def get(self, scope_name):
|
|
1614
1742
|
"""
|
|
1615
1743
|
---
|
|
1616
|
-
summary: Get
|
|
1744
|
+
summary: Get associated rules
|
|
1617
1745
|
description: Gets all associated rules for a file.
|
|
1618
1746
|
tags:
|
|
1619
1747
|
- Data Identifiers
|
|
@@ -1630,7 +1758,7 @@ class AssociatedRules(ErrorHandlingMethodView):
|
|
|
1630
1758
|
content:
|
|
1631
1759
|
application/x-json-stream:
|
|
1632
1760
|
schema:
|
|
1633
|
-
description: All associated rules for a file. Items are
|
|
1761
|
+
description: All associated rules for a file. Items are separated by new line character.
|
|
1634
1762
|
type: array
|
|
1635
1763
|
items:
|
|
1636
1764
|
description: A replication rule associated with the file. Has more fields than listed here.
|
|
@@ -1701,7 +1829,7 @@ class GUIDLookup(ErrorHandlingMethodView):
|
|
|
1701
1829
|
content:
|
|
1702
1830
|
application/x-json-stream:
|
|
1703
1831
|
schema:
|
|
1704
|
-
description: A list of all datasets associated with the guid. Items are
|
|
1832
|
+
description: A list of all datasets associated with the guid. Items are separated by new line character.
|
|
1705
1833
|
type: array
|
|
1706
1834
|
items:
|
|
1707
1835
|
description: A dataset associated with a guid.
|
|
@@ -1905,7 +2033,7 @@ class NewDIDs(ErrorHandlingMethodView):
|
|
|
1905
2033
|
content:
|
|
1906
2034
|
application/x-json-stream:
|
|
1907
2035
|
schema:
|
|
1908
|
-
description: A list of the recent dids. Items are
|
|
2036
|
+
description: A list of the recent dids. Items are separated by new line characters.
|
|
1909
2037
|
type: array
|
|
1910
2038
|
items:
|
|
1911
2039
|
description: A did.
|
|
@@ -2192,6 +2320,8 @@ def blueprint():
|
|
|
2192
2320
|
bp.add_url_rule('/resurrect', view_func=resurrect_view, methods=['post', ])
|
|
2193
2321
|
bulkmeta_view = BulkMeta.as_view('bulkmeta')
|
|
2194
2322
|
bp.add_url_rule('/bulkmeta', view_func=bulkmeta_view, methods=['post', ])
|
|
2323
|
+
files_view = BulkFiles.as_view('bulkfiles')
|
|
2324
|
+
bp.add_url_rule('/bulkfiles', view_func=files_view, methods=['post', ])
|
|
2195
2325
|
|
|
2196
2326
|
bp.after_request(response_headers)
|
|
2197
2327
|
return bp
|