rucio 37.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/__init__.py +17 -0
- rucio/alembicrevision.py +15 -0
- rucio/cli/__init__.py +14 -0
- rucio/cli/account.py +216 -0
- rucio/cli/bin_legacy/__init__.py +13 -0
- rucio/cli/bin_legacy/rucio.py +2825 -0
- rucio/cli/bin_legacy/rucio_admin.py +2500 -0
- rucio/cli/command.py +272 -0
- rucio/cli/config.py +72 -0
- rucio/cli/did.py +191 -0
- rucio/cli/download.py +128 -0
- rucio/cli/lifetime_exception.py +33 -0
- rucio/cli/replica.py +162 -0
- rucio/cli/rse.py +293 -0
- rucio/cli/rule.py +158 -0
- rucio/cli/scope.py +40 -0
- rucio/cli/subscription.py +73 -0
- rucio/cli/upload.py +60 -0
- rucio/cli/utils.py +226 -0
- rucio/client/__init__.py +15 -0
- rucio/client/accountclient.py +432 -0
- rucio/client/accountlimitclient.py +183 -0
- rucio/client/baseclient.py +983 -0
- rucio/client/client.py +120 -0
- rucio/client/configclient.py +126 -0
- rucio/client/credentialclient.py +59 -0
- rucio/client/didclient.py +868 -0
- rucio/client/diracclient.py +56 -0
- rucio/client/downloadclient.py +1783 -0
- rucio/client/exportclient.py +44 -0
- rucio/client/fileclient.py +50 -0
- rucio/client/importclient.py +42 -0
- rucio/client/lifetimeclient.py +90 -0
- rucio/client/lockclient.py +109 -0
- rucio/client/metaconventionsclient.py +140 -0
- rucio/client/pingclient.py +44 -0
- rucio/client/replicaclient.py +452 -0
- rucio/client/requestclient.py +125 -0
- rucio/client/richclient.py +317 -0
- rucio/client/rseclient.py +746 -0
- rucio/client/ruleclient.py +294 -0
- rucio/client/scopeclient.py +90 -0
- rucio/client/subscriptionclient.py +173 -0
- rucio/client/touchclient.py +82 -0
- rucio/client/uploadclient.py +969 -0
- rucio/common/__init__.py +13 -0
- rucio/common/bittorrent.py +234 -0
- rucio/common/cache.py +111 -0
- rucio/common/checksum.py +168 -0
- rucio/common/client.py +122 -0
- rucio/common/config.py +788 -0
- rucio/common/constants.py +217 -0
- rucio/common/constraints.py +17 -0
- rucio/common/didtype.py +237 -0
- rucio/common/dumper/__init__.py +342 -0
- rucio/common/dumper/consistency.py +497 -0
- rucio/common/dumper/data_models.py +362 -0
- rucio/common/dumper/path_parsing.py +75 -0
- rucio/common/exception.py +1208 -0
- rucio/common/extra.py +31 -0
- rucio/common/logging.py +420 -0
- rucio/common/pcache.py +1409 -0
- rucio/common/plugins.py +185 -0
- rucio/common/policy.py +93 -0
- rucio/common/schema/__init__.py +200 -0
- rucio/common/schema/generic.py +416 -0
- rucio/common/schema/generic_multi_vo.py +395 -0
- rucio/common/stomp_utils.py +423 -0
- rucio/common/stopwatch.py +55 -0
- rucio/common/test_rucio_server.py +154 -0
- rucio/common/types.py +483 -0
- rucio/common/utils.py +1688 -0
- rucio/core/__init__.py +13 -0
- rucio/core/account.py +496 -0
- rucio/core/account_counter.py +236 -0
- rucio/core/account_limit.py +425 -0
- rucio/core/authentication.py +620 -0
- rucio/core/config.py +437 -0
- rucio/core/credential.py +224 -0
- rucio/core/did.py +3004 -0
- rucio/core/did_meta_plugins/__init__.py +252 -0
- rucio/core/did_meta_plugins/did_column_meta.py +331 -0
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +165 -0
- rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
- rucio/core/did_meta_plugins/filter_engine.py +672 -0
- rucio/core/did_meta_plugins/json_meta.py +240 -0
- rucio/core/did_meta_plugins/mongo_meta.py +229 -0
- rucio/core/did_meta_plugins/postgres_meta.py +352 -0
- rucio/core/dirac.py +237 -0
- rucio/core/distance.py +187 -0
- rucio/core/exporter.py +59 -0
- rucio/core/heartbeat.py +363 -0
- rucio/core/identity.py +301 -0
- rucio/core/importer.py +260 -0
- rucio/core/lifetime_exception.py +377 -0
- rucio/core/lock.py +577 -0
- rucio/core/message.py +288 -0
- rucio/core/meta_conventions.py +203 -0
- rucio/core/monitor.py +448 -0
- rucio/core/naming_convention.py +195 -0
- rucio/core/nongrid_trace.py +136 -0
- rucio/core/oidc.py +1463 -0
- rucio/core/permission/__init__.py +161 -0
- rucio/core/permission/generic.py +1124 -0
- rucio/core/permission/generic_multi_vo.py +1144 -0
- rucio/core/quarantined_replica.py +224 -0
- rucio/core/replica.py +4483 -0
- rucio/core/replica_sorter.py +362 -0
- rucio/core/request.py +3091 -0
- rucio/core/rse.py +2079 -0
- rucio/core/rse_counter.py +185 -0
- rucio/core/rse_expression_parser.py +459 -0
- rucio/core/rse_selector.py +304 -0
- rucio/core/rule.py +4484 -0
- rucio/core/rule_grouping.py +1620 -0
- rucio/core/scope.py +181 -0
- rucio/core/subscription.py +362 -0
- rucio/core/topology.py +490 -0
- rucio/core/trace.py +375 -0
- rucio/core/transfer.py +1531 -0
- rucio/core/vo.py +169 -0
- rucio/core/volatile_replica.py +151 -0
- rucio/daemons/__init__.py +13 -0
- rucio/daemons/abacus/__init__.py +13 -0
- rucio/daemons/abacus/account.py +116 -0
- rucio/daemons/abacus/collection_replica.py +124 -0
- rucio/daemons/abacus/rse.py +117 -0
- rucio/daemons/atropos/__init__.py +13 -0
- rucio/daemons/atropos/atropos.py +242 -0
- rucio/daemons/auditor/__init__.py +289 -0
- rucio/daemons/auditor/hdfs.py +97 -0
- rucio/daemons/auditor/srmdumps.py +355 -0
- rucio/daemons/automatix/__init__.py +13 -0
- rucio/daemons/automatix/automatix.py +304 -0
- rucio/daemons/badreplicas/__init__.py +13 -0
- rucio/daemons/badreplicas/minos.py +322 -0
- rucio/daemons/badreplicas/minos_temporary_expiration.py +171 -0
- rucio/daemons/badreplicas/necromancer.py +196 -0
- rucio/daemons/bb8/__init__.py +13 -0
- rucio/daemons/bb8/bb8.py +353 -0
- rucio/daemons/bb8/common.py +759 -0
- rucio/daemons/bb8/nuclei_background_rebalance.py +153 -0
- rucio/daemons/bb8/t2_background_rebalance.py +153 -0
- rucio/daemons/cache/__init__.py +13 -0
- rucio/daemons/cache/consumer.py +133 -0
- rucio/daemons/common.py +405 -0
- rucio/daemons/conveyor/__init__.py +13 -0
- rucio/daemons/conveyor/common.py +562 -0
- rucio/daemons/conveyor/finisher.py +529 -0
- rucio/daemons/conveyor/poller.py +394 -0
- rucio/daemons/conveyor/preparer.py +205 -0
- rucio/daemons/conveyor/receiver.py +179 -0
- rucio/daemons/conveyor/stager.py +133 -0
- rucio/daemons/conveyor/submitter.py +403 -0
- rucio/daemons/conveyor/throttler.py +532 -0
- rucio/daemons/follower/__init__.py +13 -0
- rucio/daemons/follower/follower.py +101 -0
- rucio/daemons/hermes/__init__.py +13 -0
- rucio/daemons/hermes/hermes.py +534 -0
- rucio/daemons/judge/__init__.py +13 -0
- rucio/daemons/judge/cleaner.py +159 -0
- rucio/daemons/judge/evaluator.py +185 -0
- rucio/daemons/judge/injector.py +162 -0
- rucio/daemons/judge/repairer.py +154 -0
- rucio/daemons/oauthmanager/__init__.py +13 -0
- rucio/daemons/oauthmanager/oauthmanager.py +198 -0
- rucio/daemons/reaper/__init__.py +13 -0
- rucio/daemons/reaper/dark_reaper.py +282 -0
- rucio/daemons/reaper/reaper.py +739 -0
- rucio/daemons/replicarecoverer/__init__.py +13 -0
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +626 -0
- rucio/daemons/rsedecommissioner/__init__.py +13 -0
- rucio/daemons/rsedecommissioner/config.py +81 -0
- rucio/daemons/rsedecommissioner/profiles/__init__.py +24 -0
- rucio/daemons/rsedecommissioner/profiles/atlas.py +60 -0
- rucio/daemons/rsedecommissioner/profiles/generic.py +452 -0
- rucio/daemons/rsedecommissioner/profiles/types.py +93 -0
- rucio/daemons/rsedecommissioner/rse_decommissioner.py +280 -0
- rucio/daemons/storage/__init__.py +13 -0
- rucio/daemons/storage/consistency/__init__.py +13 -0
- rucio/daemons/storage/consistency/actions.py +848 -0
- rucio/daemons/tracer/__init__.py +13 -0
- rucio/daemons/tracer/kronos.py +511 -0
- rucio/daemons/transmogrifier/__init__.py +13 -0
- rucio/daemons/transmogrifier/transmogrifier.py +762 -0
- rucio/daemons/undertaker/__init__.py +13 -0
- rucio/daemons/undertaker/undertaker.py +137 -0
- rucio/db/__init__.py +13 -0
- rucio/db/sqla/__init__.py +52 -0
- rucio/db/sqla/constants.py +206 -0
- rucio/db/sqla/migrate_repo/__init__.py +13 -0
- rucio/db/sqla/migrate_repo/env.py +110 -0
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +70 -0
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +91 -0
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +76 -0
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +43 -0
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +50 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +68 -0
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +40 -0
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +45 -0
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +60 -0
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +40 -0
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +140 -0
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +73 -0
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +74 -0
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +43 -0
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +50 -0
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +134 -0
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +64 -0
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +39 -0
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +64 -0
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +51 -0
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +41 -0
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +43 -0
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +44 -0
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +53 -0
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +38 -0
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +47 -0
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +57 -0
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +69 -0
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +42 -0
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +46 -0
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +40 -0
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +67 -0
- rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +44 -0
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +77 -0
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +60 -0
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +72 -0
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +42 -0
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +65 -0
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +133 -0
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +76 -0
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +60 -0
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +44 -0
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +64 -0
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +40 -0
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +43 -0
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +44 -0
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +78 -0
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +41 -0
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +44 -0
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +49 -0
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +40 -0
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +63 -0
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4df2c5ddabc0_remove_temporary_dids.py +55 -0
- rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +45 -0
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +43 -0
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +47 -0
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +58 -0
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +45 -0
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +106 -0
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +55 -0
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +50 -0
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +43 -0
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +41 -0
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +91 -0
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +72 -0
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +49 -0
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +43 -0
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +53 -0
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +45 -0
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +68 -0
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +45 -0
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +94 -0
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +54 -0
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +72 -0
- rucio/db/sqla/migrate_repo/versions/a08fa8de1545_transfer_stats_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +76 -0
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +47 -0
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +121 -0
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +59 -0
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +52 -0
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +54 -0
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +64 -0
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +49 -0
- rucio/db/sqla/migrate_repo/versions/b0070f3695c8_add_deletedidmeta_table.py +57 -0
- rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +43 -0
- rucio/db/sqla/migrate_repo/versions/b5493606bbf5_fix_primary_key_for_subscription_history.py +41 -0
- rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +91 -0
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +40 -0
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +143 -0
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +76 -0
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +50 -0
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +72 -0
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +43 -0
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +65 -0
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +47 -0
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +146 -0
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +104 -0
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +44 -0
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +43 -0
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +103 -0
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +49 -0
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +104 -0
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +29 -0
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +74 -0
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +43 -0
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +37 -0
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +43 -0
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +43 -0
- rucio/db/sqla/models.py +1743 -0
- rucio/db/sqla/sautils.py +55 -0
- rucio/db/sqla/session.py +529 -0
- rucio/db/sqla/types.py +206 -0
- rucio/db/sqla/util.py +543 -0
- rucio/gateway/__init__.py +13 -0
- rucio/gateway/account.py +345 -0
- rucio/gateway/account_limit.py +363 -0
- rucio/gateway/authentication.py +381 -0
- rucio/gateway/config.py +227 -0
- rucio/gateway/credential.py +70 -0
- rucio/gateway/did.py +987 -0
- rucio/gateway/dirac.py +83 -0
- rucio/gateway/exporter.py +60 -0
- rucio/gateway/heartbeat.py +76 -0
- rucio/gateway/identity.py +189 -0
- rucio/gateway/importer.py +46 -0
- rucio/gateway/lifetime_exception.py +121 -0
- rucio/gateway/lock.py +153 -0
- rucio/gateway/meta_conventions.py +98 -0
- rucio/gateway/permission.py +74 -0
- rucio/gateway/quarantined_replica.py +79 -0
- rucio/gateway/replica.py +538 -0
- rucio/gateway/request.py +330 -0
- rucio/gateway/rse.py +632 -0
- rucio/gateway/rule.py +437 -0
- rucio/gateway/scope.py +100 -0
- rucio/gateway/subscription.py +280 -0
- rucio/gateway/vo.py +126 -0
- rucio/rse/__init__.py +96 -0
- rucio/rse/protocols/__init__.py +13 -0
- rucio/rse/protocols/bittorrent.py +194 -0
- rucio/rse/protocols/cache.py +111 -0
- rucio/rse/protocols/dummy.py +100 -0
- rucio/rse/protocols/gfal.py +708 -0
- rucio/rse/protocols/globus.py +243 -0
- rucio/rse/protocols/http_cache.py +82 -0
- rucio/rse/protocols/mock.py +123 -0
- rucio/rse/protocols/ngarc.py +209 -0
- rucio/rse/protocols/posix.py +250 -0
- rucio/rse/protocols/protocol.py +361 -0
- rucio/rse/protocols/rclone.py +365 -0
- rucio/rse/protocols/rfio.py +145 -0
- rucio/rse/protocols/srm.py +338 -0
- rucio/rse/protocols/ssh.py +414 -0
- rucio/rse/protocols/storm.py +195 -0
- rucio/rse/protocols/webdav.py +594 -0
- rucio/rse/protocols/xrootd.py +302 -0
- rucio/rse/rsemanager.py +881 -0
- rucio/rse/translation.py +260 -0
- rucio/tests/__init__.py +13 -0
- rucio/tests/common.py +280 -0
- rucio/tests/common_server.py +149 -0
- rucio/transfertool/__init__.py +13 -0
- rucio/transfertool/bittorrent.py +200 -0
- rucio/transfertool/bittorrent_driver.py +50 -0
- rucio/transfertool/bittorrent_driver_qbittorrent.py +134 -0
- rucio/transfertool/fts3.py +1600 -0
- rucio/transfertool/fts3_plugins.py +152 -0
- rucio/transfertool/globus.py +201 -0
- rucio/transfertool/globus_library.py +181 -0
- rucio/transfertool/mock.py +89 -0
- rucio/transfertool/transfertool.py +221 -0
- rucio/vcsversion.py +11 -0
- rucio/version.py +45 -0
- rucio/web/__init__.py +13 -0
- rucio/web/rest/__init__.py +13 -0
- rucio/web/rest/flaskapi/__init__.py +13 -0
- rucio/web/rest/flaskapi/authenticated_bp.py +27 -0
- rucio/web/rest/flaskapi/v1/__init__.py +13 -0
- rucio/web/rest/flaskapi/v1/accountlimits.py +236 -0
- rucio/web/rest/flaskapi/v1/accounts.py +1103 -0
- rucio/web/rest/flaskapi/v1/archives.py +102 -0
- rucio/web/rest/flaskapi/v1/auth.py +1644 -0
- rucio/web/rest/flaskapi/v1/common.py +426 -0
- rucio/web/rest/flaskapi/v1/config.py +304 -0
- rucio/web/rest/flaskapi/v1/credentials.py +213 -0
- rucio/web/rest/flaskapi/v1/dids.py +2340 -0
- rucio/web/rest/flaskapi/v1/dirac.py +116 -0
- rucio/web/rest/flaskapi/v1/export.py +75 -0
- rucio/web/rest/flaskapi/v1/heartbeats.py +127 -0
- rucio/web/rest/flaskapi/v1/identities.py +285 -0
- rucio/web/rest/flaskapi/v1/import.py +132 -0
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +312 -0
- rucio/web/rest/flaskapi/v1/locks.py +358 -0
- rucio/web/rest/flaskapi/v1/main.py +91 -0
- rucio/web/rest/flaskapi/v1/meta_conventions.py +241 -0
- rucio/web/rest/flaskapi/v1/metrics.py +36 -0
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
- rucio/web/rest/flaskapi/v1/ping.py +88 -0
- rucio/web/rest/flaskapi/v1/redirect.py +366 -0
- rucio/web/rest/flaskapi/v1/replicas.py +1894 -0
- rucio/web/rest/flaskapi/v1/requests.py +998 -0
- rucio/web/rest/flaskapi/v1/rses.py +2250 -0
- rucio/web/rest/flaskapi/v1/rules.py +854 -0
- rucio/web/rest/flaskapi/v1/scopes.py +159 -0
- rucio/web/rest/flaskapi/v1/subscriptions.py +650 -0
- rucio/web/rest/flaskapi/v1/templates/auth_crash.html +80 -0
- rucio/web/rest/flaskapi/v1/templates/auth_granted.html +82 -0
- rucio/web/rest/flaskapi/v1/traces.py +137 -0
- rucio/web/rest/flaskapi/v1/types.py +20 -0
- rucio/web/rest/flaskapi/v1/vos.py +278 -0
- rucio/web/rest/main.py +18 -0
- rucio/web/rest/metrics.py +27 -0
- rucio/web/rest/ping.py +27 -0
- rucio-37.0.0rc1.data/data/rucio/etc/alembic.ini.template +71 -0
- rucio-37.0.0rc1.data/data/rucio/etc/alembic_offline.ini.template +74 -0
- rucio-37.0.0rc1.data/data/rucio/etc/globus-config.yml.template +5 -0
- rucio-37.0.0rc1.data/data/rucio/etc/ldap.cfg.template +30 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
- rucio-37.0.0rc1.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.atlas.client.template +43 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio.cfg.template +241 -0
- rucio-37.0.0rc1.data/data/rucio/etc/rucio_multi_vo.cfg.template +217 -0
- rucio-37.0.0rc1.data/data/rucio/requirements.server.txt +297 -0
- rucio-37.0.0rc1.data/data/rucio/tools/bootstrap.py +34 -0
- rucio-37.0.0rc1.data/data/rucio/tools/merge_rucio_configs.py +144 -0
- rucio-37.0.0rc1.data/data/rucio/tools/reset_database.py +40 -0
- rucio-37.0.0rc1.data/scripts/rucio +133 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-account +74 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-collection-replica +46 -0
- rucio-37.0.0rc1.data/scripts/rucio-abacus-rse +78 -0
- rucio-37.0.0rc1.data/scripts/rucio-admin +97 -0
- rucio-37.0.0rc1.data/scripts/rucio-atropos +60 -0
- rucio-37.0.0rc1.data/scripts/rucio-auditor +206 -0
- rucio-37.0.0rc1.data/scripts/rucio-automatix +50 -0
- rucio-37.0.0rc1.data/scripts/rucio-bb8 +57 -0
- rucio-37.0.0rc1.data/scripts/rucio-cache-client +141 -0
- rucio-37.0.0rc1.data/scripts/rucio-cache-consumer +42 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-finisher +58 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-poller +66 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-preparer +37 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-receiver +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-stager +76 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-submitter +139 -0
- rucio-37.0.0rc1.data/scripts/rucio-conveyor-throttler +104 -0
- rucio-37.0.0rc1.data/scripts/rucio-dark-reaper +53 -0
- rucio-37.0.0rc1.data/scripts/rucio-dumper +160 -0
- rucio-37.0.0rc1.data/scripts/rucio-follower +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-hermes +54 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-cleaner +89 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-evaluator +137 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-injector +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-judge-repairer +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-kronos +44 -0
- rucio-37.0.0rc1.data/scripts/rucio-minos +53 -0
- rucio-37.0.0rc1.data/scripts/rucio-minos-temporary-expiration +50 -0
- rucio-37.0.0rc1.data/scripts/rucio-necromancer +120 -0
- rucio-37.0.0rc1.data/scripts/rucio-oauth-manager +63 -0
- rucio-37.0.0rc1.data/scripts/rucio-reaper +83 -0
- rucio-37.0.0rc1.data/scripts/rucio-replica-recoverer +248 -0
- rucio-37.0.0rc1.data/scripts/rucio-rse-decommissioner +66 -0
- rucio-37.0.0rc1.data/scripts/rucio-storage-consistency-actions +74 -0
- rucio-37.0.0rc1.data/scripts/rucio-transmogrifier +77 -0
- rucio-37.0.0rc1.data/scripts/rucio-undertaker +76 -0
- rucio-37.0.0rc1.dist-info/METADATA +92 -0
- rucio-37.0.0rc1.dist-info/RECORD +487 -0
- rucio-37.0.0rc1.dist-info/WHEEL +5 -0
- rucio-37.0.0rc1.dist-info/licenses/AUTHORS.rst +100 -0
- rucio-37.0.0rc1.dist-info/licenses/LICENSE +201 -0
- rucio-37.0.0rc1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,2340 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import ast
|
|
16
|
+
from json import dumps
|
|
17
|
+
|
|
18
|
+
from flask import Flask, Response, request
|
|
19
|
+
|
|
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
|
|
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
|
|
73
|
+
from rucio.web.rest.flaskapi.authenticated_bp import AuthenticatedBlueprint
|
|
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
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Scope(ErrorHandlingMethodView):
|
|
78
|
+
|
|
79
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
80
|
+
def get(self, scope):
|
|
81
|
+
"""
|
|
82
|
+
---
|
|
83
|
+
summary: Get Data Identifier
|
|
84
|
+
description: Return all data identifiers in the given scope.
|
|
85
|
+
tags:
|
|
86
|
+
- Data Identifiers
|
|
87
|
+
parameters:
|
|
88
|
+
- name: scope
|
|
89
|
+
in: path
|
|
90
|
+
description: The scope.
|
|
91
|
+
required: true
|
|
92
|
+
schema:
|
|
93
|
+
type: string
|
|
94
|
+
style: simple
|
|
95
|
+
- name: name
|
|
96
|
+
in: query
|
|
97
|
+
description: The name of the data identifier (did).
|
|
98
|
+
required: false
|
|
99
|
+
schema:
|
|
100
|
+
type: string
|
|
101
|
+
- name: recursive
|
|
102
|
+
in: query
|
|
103
|
+
description: If true, retrieves child identifiers recursively for non-file types.
|
|
104
|
+
required: false
|
|
105
|
+
schema:
|
|
106
|
+
type: boolean
|
|
107
|
+
responses:
|
|
108
|
+
200:
|
|
109
|
+
description: OK
|
|
110
|
+
content:
|
|
111
|
+
application/x-json-stream:
|
|
112
|
+
schema:
|
|
113
|
+
description: Line-separated dictionary of dids.
|
|
114
|
+
type: array
|
|
115
|
+
items:
|
|
116
|
+
type: object
|
|
117
|
+
description: Data identifier
|
|
118
|
+
properties:
|
|
119
|
+
scope:
|
|
120
|
+
type: string
|
|
121
|
+
description: The scope of the did.
|
|
122
|
+
name:
|
|
123
|
+
type: string
|
|
124
|
+
description: The name of the did.
|
|
125
|
+
type:
|
|
126
|
+
type: string
|
|
127
|
+
description: The type of the did.
|
|
128
|
+
enum: ['F', 'D', 'C', 'A', 'X', 'Y', 'Z']
|
|
129
|
+
parent:
|
|
130
|
+
type: string
|
|
131
|
+
description: The parent of the did.
|
|
132
|
+
level:
|
|
133
|
+
type: integer
|
|
134
|
+
description: The level of the did.
|
|
135
|
+
401:
|
|
136
|
+
description: Invalid Auth Token
|
|
137
|
+
404:
|
|
138
|
+
description: No Dids found
|
|
139
|
+
406:
|
|
140
|
+
description: Not acceptable
|
|
141
|
+
"""
|
|
142
|
+
try:
|
|
143
|
+
def generate(name, recursive, vo):
|
|
144
|
+
for did in scope_list(scope=scope, name=name, recursive=recursive, vo=vo):
|
|
145
|
+
yield render_json(**did) + '\n'
|
|
146
|
+
|
|
147
|
+
recursive = request.args.get('recursive', 'false').lower() in ['true', '1']
|
|
148
|
+
|
|
149
|
+
return try_stream(
|
|
150
|
+
generate(
|
|
151
|
+
name=request.args.get('name', default=None),
|
|
152
|
+
recursive=recursive,
|
|
153
|
+
vo=request.environ.get('vo')
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
except DataIdentifierNotFound as error:
|
|
157
|
+
return generate_http_error_flask(404, error)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class Search(ErrorHandlingMethodView):
|
|
161
|
+
|
|
162
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
163
|
+
def get(self, scope):
|
|
164
|
+
"""
|
|
165
|
+
---
|
|
166
|
+
summary: List Data identifier
|
|
167
|
+
description: List all data identifiers in a scope which match a given metadata.
|
|
168
|
+
tags:
|
|
169
|
+
- Data Identifiers
|
|
170
|
+
parameters:
|
|
171
|
+
- name: scope
|
|
172
|
+
in: path
|
|
173
|
+
description: The scope of the data identifiers.
|
|
174
|
+
schema:
|
|
175
|
+
type: string
|
|
176
|
+
style: simple
|
|
177
|
+
- name: type
|
|
178
|
+
in: query
|
|
179
|
+
description: The did type to search for.
|
|
180
|
+
schema:
|
|
181
|
+
type: string
|
|
182
|
+
enum: ['all', 'collection', 'container', 'dataset', 'file']
|
|
183
|
+
default: 'collection'
|
|
184
|
+
- name: limit
|
|
185
|
+
in: query
|
|
186
|
+
description: The maximum number od dids returned.
|
|
187
|
+
schema:
|
|
188
|
+
type: integer
|
|
189
|
+
- name: long
|
|
190
|
+
in: query
|
|
191
|
+
description: Provides a longer output, otherwise just prints names.
|
|
192
|
+
schema:
|
|
193
|
+
type: boolean
|
|
194
|
+
default: false
|
|
195
|
+
- name: recursive
|
|
196
|
+
in: query
|
|
197
|
+
description: Recursively list chilred.
|
|
198
|
+
schema:
|
|
199
|
+
type: boolean
|
|
200
|
+
- name: created_before
|
|
201
|
+
in: query
|
|
202
|
+
description: Date string in RFC-1123 format where the creation date was earlier.
|
|
203
|
+
schema:
|
|
204
|
+
type: string
|
|
205
|
+
- name: created_after
|
|
206
|
+
in: query
|
|
207
|
+
description: Date string in RFC-1123 format where the creation date was later.
|
|
208
|
+
schema:
|
|
209
|
+
type: string
|
|
210
|
+
- name: length
|
|
211
|
+
in: query
|
|
212
|
+
description: Exact number of attached DIDs.
|
|
213
|
+
schema:
|
|
214
|
+
type: integer
|
|
215
|
+
- name: length.gt
|
|
216
|
+
in: query
|
|
217
|
+
description: Number of attached DIDs greater than.
|
|
218
|
+
schema:
|
|
219
|
+
type: integer
|
|
220
|
+
- name: length.lt
|
|
221
|
+
in: query
|
|
222
|
+
description: Number of attached DIDs less than.
|
|
223
|
+
schema:
|
|
224
|
+
type: integer
|
|
225
|
+
- name: length.gte
|
|
226
|
+
in: query
|
|
227
|
+
description: Number of attached DIDs greater than or equal to
|
|
228
|
+
schema:
|
|
229
|
+
type: integer
|
|
230
|
+
- name: length.lte
|
|
231
|
+
in: query
|
|
232
|
+
description: Number of attached DIDs less than or equal to.
|
|
233
|
+
schema:
|
|
234
|
+
type: integer
|
|
235
|
+
- name: name
|
|
236
|
+
in: query
|
|
237
|
+
description: Name or pattern of a did.
|
|
238
|
+
schema:
|
|
239
|
+
type: string
|
|
240
|
+
responses:
|
|
241
|
+
200:
|
|
242
|
+
description: OK
|
|
243
|
+
content:
|
|
244
|
+
application/x-json-stream:
|
|
245
|
+
schema:
|
|
246
|
+
description: Line separated name of DIDs or dictionaries of DIDs for long option.
|
|
247
|
+
type: array
|
|
248
|
+
items:
|
|
249
|
+
type: object
|
|
250
|
+
description: the name of a DID or a dictionarie of a DID for long option.
|
|
251
|
+
401:
|
|
252
|
+
description: Invalid Auth Token
|
|
253
|
+
404:
|
|
254
|
+
description: Invalid key in filter.
|
|
255
|
+
406:
|
|
256
|
+
description: Not acceptable
|
|
257
|
+
409:
|
|
258
|
+
description: Wrong did type
|
|
259
|
+
"""
|
|
260
|
+
filters = request.args.get('filters', default=None)
|
|
261
|
+
if filters is not None:
|
|
262
|
+
filters = ast.literal_eval(filters)
|
|
263
|
+
else:
|
|
264
|
+
# backwards compatibility for created*, length* and name filters passed through as request args
|
|
265
|
+
filters = {}
|
|
266
|
+
for arg, value in request.args.copy().items():
|
|
267
|
+
if arg not in ['type', 'limit', 'long', 'recursive']:
|
|
268
|
+
filters[arg] = value
|
|
269
|
+
filters = [filters]
|
|
270
|
+
|
|
271
|
+
did_type = request.args.get('type', default=None)
|
|
272
|
+
limit = request.args.get('limit', default=None)
|
|
273
|
+
long = request.args.get('long', type=['True', '1'].__contains__, default=False)
|
|
274
|
+
recursive = request.args.get('recursive', type='True'.__eq__, default=False)
|
|
275
|
+
try:
|
|
276
|
+
def generate(vo):
|
|
277
|
+
for did in list_dids(scope=scope, filters=filters, did_type=did_type, limit=limit, long=long, recursive=recursive, vo=vo):
|
|
278
|
+
yield dumps(did) + '\n'
|
|
279
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
280
|
+
except UnsupportedOperation as error:
|
|
281
|
+
return generate_http_error_flask(409, error)
|
|
282
|
+
except KeyNotFound as error:
|
|
283
|
+
return generate_http_error_flask(404, error)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class BulkDIDS(ErrorHandlingMethodView):
|
|
287
|
+
|
|
288
|
+
@check_accept_header_wrapper_flask(['application/json'])
|
|
289
|
+
def post(self):
|
|
290
|
+
"""
|
|
291
|
+
---
|
|
292
|
+
summary: Add Dids bulk
|
|
293
|
+
description: Add new Dids in bulk.
|
|
294
|
+
tags:
|
|
295
|
+
- Data Identifiers
|
|
296
|
+
requestBody:
|
|
297
|
+
content:
|
|
298
|
+
application/json:
|
|
299
|
+
schema:
|
|
300
|
+
type: array
|
|
301
|
+
items:
|
|
302
|
+
description: One did to add.
|
|
303
|
+
type: object
|
|
304
|
+
required:
|
|
305
|
+
- scope
|
|
306
|
+
- name
|
|
307
|
+
- type
|
|
308
|
+
properties:
|
|
309
|
+
scope:
|
|
310
|
+
description: The did scope.
|
|
311
|
+
type: string
|
|
312
|
+
name:
|
|
313
|
+
description: The did name.
|
|
314
|
+
type: string
|
|
315
|
+
type:
|
|
316
|
+
description: The type of the did.
|
|
317
|
+
type: string
|
|
318
|
+
enum: ["F", "D", "C", "A", "X", "Y", "Z"]
|
|
319
|
+
account:
|
|
320
|
+
description: The account associated with the did.
|
|
321
|
+
type: string
|
|
322
|
+
statuses:
|
|
323
|
+
description: The monotonic status
|
|
324
|
+
type: string
|
|
325
|
+
responses:
|
|
326
|
+
201:
|
|
327
|
+
description: OK
|
|
328
|
+
content:
|
|
329
|
+
application/json:
|
|
330
|
+
schema:
|
|
331
|
+
type: string
|
|
332
|
+
enum: ["Created"]
|
|
333
|
+
401:
|
|
334
|
+
description: Invalid Auth Token
|
|
335
|
+
406:
|
|
336
|
+
description: Not acceptable
|
|
337
|
+
409:
|
|
338
|
+
description: Did already exists
|
|
339
|
+
"""
|
|
340
|
+
dids = json_list()
|
|
341
|
+
try:
|
|
342
|
+
add_dids(dids=dids, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'))
|
|
343
|
+
except DataIdentifierNotFound as error:
|
|
344
|
+
return generate_http_error_flask(404, error)
|
|
345
|
+
except (DuplicateContent, DataIdentifierAlreadyExists, UnsupportedOperation) as error:
|
|
346
|
+
return generate_http_error_flask(409, error)
|
|
347
|
+
except AccessDenied as error:
|
|
348
|
+
return generate_http_error_flask(401, error)
|
|
349
|
+
return 'Created', 201
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
class Attachments(ErrorHandlingMethodView):
|
|
353
|
+
|
|
354
|
+
def post(self):
|
|
355
|
+
"""
|
|
356
|
+
---
|
|
357
|
+
summary: Attach did to did
|
|
358
|
+
description: Attaches a did to another did
|
|
359
|
+
tags:
|
|
360
|
+
- Data Identifiers
|
|
361
|
+
requestBody:
|
|
362
|
+
content:
|
|
363
|
+
'application/json':
|
|
364
|
+
schema:
|
|
365
|
+
oneOf:
|
|
366
|
+
- description: An array containing all dids. Duplicates are not ignored.
|
|
367
|
+
type: array
|
|
368
|
+
required:
|
|
369
|
+
- scope
|
|
370
|
+
- name
|
|
371
|
+
- dids
|
|
372
|
+
properties:
|
|
373
|
+
scope:
|
|
374
|
+
description: The scope of the did.
|
|
375
|
+
type: string
|
|
376
|
+
name:
|
|
377
|
+
description: The name of the did.
|
|
378
|
+
type: string
|
|
379
|
+
dids:
|
|
380
|
+
description: The dids associated to the did.
|
|
381
|
+
type: array
|
|
382
|
+
items:
|
|
383
|
+
type: object
|
|
384
|
+
description: A did.
|
|
385
|
+
required:
|
|
386
|
+
- scope
|
|
387
|
+
- name
|
|
388
|
+
properties:
|
|
389
|
+
scope:
|
|
390
|
+
description: The scope of the did.
|
|
391
|
+
type: string
|
|
392
|
+
name:
|
|
393
|
+
description: The name of the did.
|
|
394
|
+
type: string
|
|
395
|
+
rse_id:
|
|
396
|
+
description: The rse id of the did.
|
|
397
|
+
type: string
|
|
398
|
+
- type: object
|
|
399
|
+
required:
|
|
400
|
+
- attachments
|
|
401
|
+
properties:
|
|
402
|
+
ignore_duplicates:
|
|
403
|
+
description: If duplicates should be ignored.
|
|
404
|
+
type: boolean
|
|
405
|
+
default: false
|
|
406
|
+
attachments:
|
|
407
|
+
description: An array containing all dids. Duplicates are not ignored.
|
|
408
|
+
type: array
|
|
409
|
+
required:
|
|
410
|
+
- scope
|
|
411
|
+
- name
|
|
412
|
+
- dids
|
|
413
|
+
properties:
|
|
414
|
+
scope:
|
|
415
|
+
description: The scope of the did.
|
|
416
|
+
type: string
|
|
417
|
+
name:
|
|
418
|
+
description: The name of the did.
|
|
419
|
+
type: string
|
|
420
|
+
dids:
|
|
421
|
+
description: The dids associated to the did.
|
|
422
|
+
type: array
|
|
423
|
+
items:
|
|
424
|
+
type: object
|
|
425
|
+
description: A did.
|
|
426
|
+
required:
|
|
427
|
+
- scope
|
|
428
|
+
- name
|
|
429
|
+
properties:
|
|
430
|
+
scope:
|
|
431
|
+
description: The scope of the did.
|
|
432
|
+
type: string
|
|
433
|
+
name:
|
|
434
|
+
description: The name of the did.
|
|
435
|
+
type: string
|
|
436
|
+
rse_id:
|
|
437
|
+
description: The rse id of the did.
|
|
438
|
+
type: string
|
|
439
|
+
responses:
|
|
440
|
+
200:
|
|
441
|
+
description: OK
|
|
442
|
+
content:
|
|
443
|
+
application/json:
|
|
444
|
+
schema:
|
|
445
|
+
type: string
|
|
446
|
+
enum: ["Created"]
|
|
447
|
+
401:
|
|
448
|
+
description: Invalid Auth Token
|
|
449
|
+
404:
|
|
450
|
+
description: Not found
|
|
451
|
+
406:
|
|
452
|
+
description: Not acceptable
|
|
453
|
+
"""
|
|
454
|
+
parameters = json_parse((dict, list))
|
|
455
|
+
if isinstance(parameters, list):
|
|
456
|
+
attachments = parameters
|
|
457
|
+
ignore_duplicate = False
|
|
458
|
+
elif isinstance(parameters, dict):
|
|
459
|
+
attachments = param_get(parameters, 'attachments')
|
|
460
|
+
ignore_duplicate = param_get(parameters, 'ignore_duplicate', default=False)
|
|
461
|
+
else:
|
|
462
|
+
return generate_http_error_flask(406, exc="Invalid attachment format.")
|
|
463
|
+
|
|
464
|
+
try:
|
|
465
|
+
attach_dids_to_dids(attachments=attachments, ignore_duplicate=ignore_duplicate, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'))
|
|
466
|
+
except DataIdentifierNotFound as error:
|
|
467
|
+
return generate_http_error_flask(404, error)
|
|
468
|
+
except (DuplicateContent, DataIdentifierAlreadyExists, UnsupportedOperation, FileAlreadyExists) as error:
|
|
469
|
+
return generate_http_error_flask(409, error)
|
|
470
|
+
except AccessDenied as error:
|
|
471
|
+
return generate_http_error_flask(401, error)
|
|
472
|
+
except FileConsistencyMismatch as error:
|
|
473
|
+
return generate_http_error_flask(412, error)
|
|
474
|
+
|
|
475
|
+
return 'Created', 201
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
class DIDs(ErrorHandlingMethodView):
|
|
479
|
+
|
|
480
|
+
@check_accept_header_wrapper_flask(['application/json'])
|
|
481
|
+
def get(self, scope_name):
|
|
482
|
+
"""
|
|
483
|
+
---
|
|
484
|
+
summary: Get did
|
|
485
|
+
description: Get a single data identifier.
|
|
486
|
+
tags:
|
|
487
|
+
- Data identifiers
|
|
488
|
+
parameters:
|
|
489
|
+
- name: scope_name
|
|
490
|
+
in: path
|
|
491
|
+
description: The scope and the name of the did.
|
|
492
|
+
schema:
|
|
493
|
+
type: string
|
|
494
|
+
style: simple
|
|
495
|
+
- name: dynamic_depth
|
|
496
|
+
in: query
|
|
497
|
+
description: The DID type at which to stop the dynamic length/size estimation
|
|
498
|
+
schema:
|
|
499
|
+
type: string
|
|
500
|
+
enum: ["FILE", "DATASET"]
|
|
501
|
+
- name: dynamic
|
|
502
|
+
in: query
|
|
503
|
+
description: Same as dynamic_depth = "FILE"
|
|
504
|
+
deprecated: true
|
|
505
|
+
schema:
|
|
506
|
+
type: string
|
|
507
|
+
responses:
|
|
508
|
+
200:
|
|
509
|
+
description: OK
|
|
510
|
+
content:
|
|
511
|
+
application/json:
|
|
512
|
+
schema:
|
|
513
|
+
oneOf:
|
|
514
|
+
- description: A single file did.
|
|
515
|
+
type: object
|
|
516
|
+
properties:
|
|
517
|
+
scope:
|
|
518
|
+
description: The scope of the did.
|
|
519
|
+
type: string
|
|
520
|
+
name:
|
|
521
|
+
description: The name of the did.
|
|
522
|
+
type: string
|
|
523
|
+
type:
|
|
524
|
+
description: The type of the string.
|
|
525
|
+
type: string
|
|
526
|
+
account:
|
|
527
|
+
description: The associated account.
|
|
528
|
+
type: string
|
|
529
|
+
bytes:
|
|
530
|
+
description: The size in bytes.
|
|
531
|
+
type: integer
|
|
532
|
+
length:
|
|
533
|
+
description: The number of files. Corresponses to 1.
|
|
534
|
+
type: integer
|
|
535
|
+
enum: [1]
|
|
536
|
+
md5:
|
|
537
|
+
description: md5 checksum.
|
|
538
|
+
type: string
|
|
539
|
+
adler32:
|
|
540
|
+
description: adler32 checksum.
|
|
541
|
+
type: string
|
|
542
|
+
- description: A single file did.
|
|
543
|
+
type: object
|
|
544
|
+
properties:
|
|
545
|
+
scope:
|
|
546
|
+
description: The scope of the did.
|
|
547
|
+
type: string
|
|
548
|
+
name:
|
|
549
|
+
description: The name of the did.
|
|
550
|
+
type: string
|
|
551
|
+
type:
|
|
552
|
+
description: The type of the string.
|
|
553
|
+
type: string
|
|
554
|
+
account:
|
|
555
|
+
description: The associated account.
|
|
556
|
+
type: string
|
|
557
|
+
open:
|
|
558
|
+
description: If the did is write open.
|
|
559
|
+
type: boolean
|
|
560
|
+
monotonic:
|
|
561
|
+
description: If the did is monotonic.
|
|
562
|
+
type: boolean
|
|
563
|
+
expired_at:
|
|
564
|
+
description: When the did expired.
|
|
565
|
+
type: string
|
|
566
|
+
length:
|
|
567
|
+
description: The number of associated dids.
|
|
568
|
+
type: number
|
|
569
|
+
bytes:
|
|
570
|
+
description: The size in bytes.
|
|
571
|
+
type: number
|
|
572
|
+
401:
|
|
573
|
+
description: Invalid Auth Token
|
|
574
|
+
404:
|
|
575
|
+
description: Scope not found
|
|
576
|
+
406:
|
|
577
|
+
description: Not acceptable
|
|
578
|
+
"""
|
|
579
|
+
try:
|
|
580
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
581
|
+
dynamic_depth = None
|
|
582
|
+
if 'dynamic_depth' in request.args:
|
|
583
|
+
orig = request.args['dynamic_depth'].upper()
|
|
584
|
+
if orig == 'DATASET':
|
|
585
|
+
dynamic_depth = DIDType.DATASET
|
|
586
|
+
elif orig == 'FILE':
|
|
587
|
+
dynamic_depth = DIDType.FILE
|
|
588
|
+
else:
|
|
589
|
+
dynamic_depth = None
|
|
590
|
+
elif 'dynamic' in request.args:
|
|
591
|
+
dynamic_depth = DIDType.FILE
|
|
592
|
+
did = get_did(scope=scope, name=name, dynamic_depth=dynamic_depth, vo=request.environ.get('vo'))
|
|
593
|
+
return Response(render_json(**did), content_type='application/json')
|
|
594
|
+
except ValueError as error:
|
|
595
|
+
return generate_http_error_flask(400, error)
|
|
596
|
+
except (ScopeNotFound, DataIdentifierNotFound) as error:
|
|
597
|
+
return generate_http_error_flask(404, error)
|
|
598
|
+
|
|
599
|
+
def post(self, scope_name):
|
|
600
|
+
"""
|
|
601
|
+
---
|
|
602
|
+
summary: Create did
|
|
603
|
+
description: Create a new data identifier.
|
|
604
|
+
tags:
|
|
605
|
+
- Data Identifiers
|
|
606
|
+
parameters:
|
|
607
|
+
- name: scope_name
|
|
608
|
+
in: path
|
|
609
|
+
description: The scope and the name of the did.
|
|
610
|
+
schema:
|
|
611
|
+
type: string
|
|
612
|
+
style: simple
|
|
613
|
+
requestBody:
|
|
614
|
+
content:
|
|
615
|
+
'application/json':
|
|
616
|
+
schema:
|
|
617
|
+
type: object
|
|
618
|
+
required:
|
|
619
|
+
- type
|
|
620
|
+
properties:
|
|
621
|
+
type:
|
|
622
|
+
description: The type of the did.
|
|
623
|
+
type: string
|
|
624
|
+
statuses:
|
|
625
|
+
description: The statuses of the did.
|
|
626
|
+
type: string
|
|
627
|
+
meta:
|
|
628
|
+
description: The meta of the did.
|
|
629
|
+
type: string
|
|
630
|
+
rules:
|
|
631
|
+
description: The rules associated with the did.
|
|
632
|
+
type: array
|
|
633
|
+
items:
|
|
634
|
+
type: object
|
|
635
|
+
description: A rule.
|
|
636
|
+
lifetime:
|
|
637
|
+
description: The lifetime of the did.
|
|
638
|
+
type: string
|
|
639
|
+
dids:
|
|
640
|
+
description: The dids associated with the did.
|
|
641
|
+
type: array
|
|
642
|
+
items:
|
|
643
|
+
type: object
|
|
644
|
+
description: The did associated with a did.
|
|
645
|
+
properties:
|
|
646
|
+
scope:
|
|
647
|
+
description: The scope of the did.
|
|
648
|
+
type: string
|
|
649
|
+
name:
|
|
650
|
+
description: The name of the did.
|
|
651
|
+
type: string
|
|
652
|
+
rse:
|
|
653
|
+
description: The rse associated with the did.
|
|
654
|
+
type: string
|
|
655
|
+
responses:
|
|
656
|
+
201:
|
|
657
|
+
description: OK
|
|
658
|
+
content:
|
|
659
|
+
application/json:
|
|
660
|
+
schema:
|
|
661
|
+
type: string
|
|
662
|
+
enum: ['Created']
|
|
663
|
+
401:
|
|
664
|
+
description: Invalid Auth Token
|
|
665
|
+
404:
|
|
666
|
+
description: Did or scope not found
|
|
667
|
+
409:
|
|
668
|
+
description: Did already exists
|
|
669
|
+
"""
|
|
670
|
+
try:
|
|
671
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
672
|
+
except ValueError as error:
|
|
673
|
+
return generate_http_error_flask(400, error)
|
|
674
|
+
|
|
675
|
+
parameters = json_parameters()
|
|
676
|
+
type_param = param_get(parameters, 'type')
|
|
677
|
+
|
|
678
|
+
try:
|
|
679
|
+
add_did(
|
|
680
|
+
scope=scope,
|
|
681
|
+
name=name,
|
|
682
|
+
did_type=type_param,
|
|
683
|
+
statuses=param_get(parameters, 'statuses', default={}),
|
|
684
|
+
meta=param_get(parameters, 'meta', default={}),
|
|
685
|
+
rules=param_get(parameters, 'rules', default=[]),
|
|
686
|
+
lifetime=param_get(parameters, 'lifetime', default=None),
|
|
687
|
+
dids=param_get(parameters, 'dids', default=[]),
|
|
688
|
+
rse=param_get(parameters, 'rse', default=None),
|
|
689
|
+
issuer=request.environ.get('issuer'),
|
|
690
|
+
vo=request.environ.get('vo'),
|
|
691
|
+
)
|
|
692
|
+
except (InvalidObject, InvalidPath) as error:
|
|
693
|
+
return generate_http_error_flask(400, error)
|
|
694
|
+
except (DataIdentifierNotFound, ScopeNotFound) as error:
|
|
695
|
+
return generate_http_error_flask(404, error)
|
|
696
|
+
except (DuplicateContent, DataIdentifierAlreadyExists, UnsupportedOperation) as error:
|
|
697
|
+
return generate_http_error_flask(409, error)
|
|
698
|
+
except AccessDenied as error:
|
|
699
|
+
return generate_http_error_flask(401, error)
|
|
700
|
+
except DatabaseException as error:
|
|
701
|
+
if 'DELETED_DIDS_PK violated' in str(error):
|
|
702
|
+
return generate_http_error_flask(
|
|
703
|
+
status_code=406,
|
|
704
|
+
exc=error.__class__.__name__,
|
|
705
|
+
exc_msg=str('A deleted DID {} with scope {} is reused'.format(name, scope))
|
|
706
|
+
)
|
|
707
|
+
else:
|
|
708
|
+
return generate_http_error_flask(406, error)
|
|
709
|
+
|
|
710
|
+
return 'Created', 201
|
|
711
|
+
|
|
712
|
+
def put(self, scope_name):
|
|
713
|
+
"""
|
|
714
|
+
---
|
|
715
|
+
summary: Update did
|
|
716
|
+
description: Update a did.
|
|
717
|
+
tags:
|
|
718
|
+
- Data Identifiers
|
|
719
|
+
parameters:
|
|
720
|
+
- name: scope_name
|
|
721
|
+
in: path
|
|
722
|
+
description: The scope and the name of the did.
|
|
723
|
+
schema:
|
|
724
|
+
type: string
|
|
725
|
+
style: simple
|
|
726
|
+
requestBody:
|
|
727
|
+
content:
|
|
728
|
+
'application/json':
|
|
729
|
+
schema:
|
|
730
|
+
type: object
|
|
731
|
+
properties:
|
|
732
|
+
open:
|
|
733
|
+
description: The open status
|
|
734
|
+
type: boolean
|
|
735
|
+
responses:
|
|
736
|
+
200:
|
|
737
|
+
description: OK
|
|
738
|
+
401:
|
|
739
|
+
description: Invalid Auth Token
|
|
740
|
+
404:
|
|
741
|
+
description: Did not found
|
|
742
|
+
409:
|
|
743
|
+
description: Wrong status
|
|
744
|
+
"""
|
|
745
|
+
try:
|
|
746
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
747
|
+
except ValueError as error:
|
|
748
|
+
return generate_http_error_flask(400, error)
|
|
749
|
+
|
|
750
|
+
parameters = json_parameters()
|
|
751
|
+
|
|
752
|
+
try:
|
|
753
|
+
set_status(scope=scope, name=name, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'), **parameters)
|
|
754
|
+
except DataIdentifierNotFound as error:
|
|
755
|
+
return generate_http_error_flask(404, error)
|
|
756
|
+
except (UnsupportedStatus, UnsupportedOperation) as error:
|
|
757
|
+
return generate_http_error_flask(409, error)
|
|
758
|
+
except AccessDenied as error:
|
|
759
|
+
return generate_http_error_flask(401, error)
|
|
760
|
+
|
|
761
|
+
return '', 200
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
class Attachment(ErrorHandlingMethodView):
|
|
765
|
+
|
|
766
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
767
|
+
def get(self, scope_name):
|
|
768
|
+
"""
|
|
769
|
+
---
|
|
770
|
+
summary: Get did
|
|
771
|
+
description: Returns the contents of a data identifier.
|
|
772
|
+
tags:
|
|
773
|
+
- Data Identifiers
|
|
774
|
+
parameters:
|
|
775
|
+
- name: scope_name
|
|
776
|
+
in: path
|
|
777
|
+
description: The scope and the name of the did.
|
|
778
|
+
schema:
|
|
779
|
+
type: string
|
|
780
|
+
style: simple
|
|
781
|
+
responses:
|
|
782
|
+
200:
|
|
783
|
+
description: Did found
|
|
784
|
+
content:
|
|
785
|
+
application/x-json-stream:
|
|
786
|
+
schema:
|
|
787
|
+
description: The contents of a did. Items are line separated.
|
|
788
|
+
type: array
|
|
789
|
+
items:
|
|
790
|
+
type: object
|
|
791
|
+
required:
|
|
792
|
+
- scope
|
|
793
|
+
- name
|
|
794
|
+
- type
|
|
795
|
+
- bytes
|
|
796
|
+
- adler32
|
|
797
|
+
- md5
|
|
798
|
+
properties:
|
|
799
|
+
scope:
|
|
800
|
+
description: The scope of the did.
|
|
801
|
+
type: string
|
|
802
|
+
name:
|
|
803
|
+
description: The name of the did.
|
|
804
|
+
type: string
|
|
805
|
+
type:
|
|
806
|
+
description: The type of the did.
|
|
807
|
+
type: string
|
|
808
|
+
bytes:
|
|
809
|
+
description: The size of the did.
|
|
810
|
+
type: number
|
|
811
|
+
adler32:
|
|
812
|
+
description: The adler32 checksum of the did.
|
|
813
|
+
type: string
|
|
814
|
+
md5:
|
|
815
|
+
description: The md5 checksum of the did.
|
|
816
|
+
type: string
|
|
817
|
+
401:
|
|
818
|
+
description: Invalid Auth Token
|
|
819
|
+
404:
|
|
820
|
+
description: Scope not found
|
|
821
|
+
406:
|
|
822
|
+
description: Not acceptable
|
|
823
|
+
"""
|
|
824
|
+
try:
|
|
825
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
826
|
+
|
|
827
|
+
def generate(vo):
|
|
828
|
+
for did in list_content(scope=scope, name=name, vo=vo):
|
|
829
|
+
yield render_json(**did) + '\n'
|
|
830
|
+
|
|
831
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
832
|
+
except ValueError as error:
|
|
833
|
+
return generate_http_error_flask(400, error)
|
|
834
|
+
except DataIdentifierNotFound as error:
|
|
835
|
+
return generate_http_error_flask(404, error)
|
|
836
|
+
|
|
837
|
+
def post(self, scope_name):
|
|
838
|
+
"""
|
|
839
|
+
---
|
|
840
|
+
summary: Add dids to did
|
|
841
|
+
description: Append data identifiers to data identifiers.
|
|
842
|
+
tags:
|
|
843
|
+
- Data Identifiers
|
|
844
|
+
parameters:
|
|
845
|
+
- name: scope_name
|
|
846
|
+
in: path
|
|
847
|
+
description: The scope and the name of the did.
|
|
848
|
+
schema:
|
|
849
|
+
type: string
|
|
850
|
+
style: simple
|
|
851
|
+
requestBody:
|
|
852
|
+
content:
|
|
853
|
+
'application/json':
|
|
854
|
+
schema:
|
|
855
|
+
type: object
|
|
856
|
+
required:
|
|
857
|
+
- dids
|
|
858
|
+
properties:
|
|
859
|
+
rse:
|
|
860
|
+
description: The name of the rse.
|
|
861
|
+
type: string
|
|
862
|
+
account:
|
|
863
|
+
description: The account which attaches the dids.
|
|
864
|
+
type: string
|
|
865
|
+
dids:
|
|
866
|
+
description: The dids to attach.
|
|
867
|
+
type: object
|
|
868
|
+
properties:
|
|
869
|
+
account:
|
|
870
|
+
description: The account attaching the did.
|
|
871
|
+
type: string
|
|
872
|
+
scope:
|
|
873
|
+
description: The scope of the did.
|
|
874
|
+
type: string
|
|
875
|
+
name:
|
|
876
|
+
description: The name of the did.
|
|
877
|
+
type: string
|
|
878
|
+
responses:
|
|
879
|
+
201:
|
|
880
|
+
description: OK
|
|
881
|
+
content:
|
|
882
|
+
application/json:
|
|
883
|
+
schema:
|
|
884
|
+
type: string
|
|
885
|
+
enum: ["Created"]
|
|
886
|
+
401:
|
|
887
|
+
description: Invalid Auth Token
|
|
888
|
+
404:
|
|
889
|
+
description: Did not found
|
|
890
|
+
406:
|
|
891
|
+
description: Not acceptable
|
|
892
|
+
409:
|
|
893
|
+
description: Already attached
|
|
894
|
+
"""
|
|
895
|
+
try:
|
|
896
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
897
|
+
except ValueError as error:
|
|
898
|
+
return generate_http_error_flask(400, error)
|
|
899
|
+
|
|
900
|
+
attachments = json_parameters()
|
|
901
|
+
|
|
902
|
+
try:
|
|
903
|
+
attach_dids(scope=scope, name=name, attachment=attachments, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'))
|
|
904
|
+
except InvalidPath as error:
|
|
905
|
+
return generate_http_error_flask(400, error)
|
|
906
|
+
except (DataIdentifierNotFound, RSENotFound) as error:
|
|
907
|
+
return generate_http_error_flask(404, error)
|
|
908
|
+
except (DuplicateContent, UnsupportedOperation, FileAlreadyExists) as error:
|
|
909
|
+
return generate_http_error_flask(409, error)
|
|
910
|
+
except AccessDenied as error:
|
|
911
|
+
return generate_http_error_flask(401, error)
|
|
912
|
+
|
|
913
|
+
return 'Created', 201
|
|
914
|
+
|
|
915
|
+
def delete(self, scope_name):
|
|
916
|
+
"""
|
|
917
|
+
---
|
|
918
|
+
summary: Detach dids from did
|
|
919
|
+
description: Detach data identifiers from data identifiers.
|
|
920
|
+
tags:
|
|
921
|
+
- Data Identifiers
|
|
922
|
+
parameters:
|
|
923
|
+
- name: scope_name
|
|
924
|
+
in: path
|
|
925
|
+
description: The scope and the name of the did.
|
|
926
|
+
schema:
|
|
927
|
+
type: string
|
|
928
|
+
style: simple
|
|
929
|
+
requestBody:
|
|
930
|
+
content:
|
|
931
|
+
'application/json':
|
|
932
|
+
schema:
|
|
933
|
+
type: object
|
|
934
|
+
required:
|
|
935
|
+
- dids
|
|
936
|
+
properties:
|
|
937
|
+
dids:
|
|
938
|
+
description: The dids to detach.
|
|
939
|
+
type: array
|
|
940
|
+
items:
|
|
941
|
+
type: object
|
|
942
|
+
properties:
|
|
943
|
+
scope:
|
|
944
|
+
description: The scope of the did.
|
|
945
|
+
type: string
|
|
946
|
+
name:
|
|
947
|
+
description: The name of the did.
|
|
948
|
+
type: string
|
|
949
|
+
responses:
|
|
950
|
+
200:
|
|
951
|
+
description: OK
|
|
952
|
+
401:
|
|
953
|
+
description: Invalid Auth Token
|
|
954
|
+
404:
|
|
955
|
+
description: Did not found
|
|
956
|
+
"""
|
|
957
|
+
try:
|
|
958
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
959
|
+
except ValueError as error:
|
|
960
|
+
return generate_http_error_flask(400, error)
|
|
961
|
+
|
|
962
|
+
parameters = json_parameters()
|
|
963
|
+
dids = param_get(parameters, 'dids')
|
|
964
|
+
|
|
965
|
+
try:
|
|
966
|
+
detach_dids(scope=scope, name=name, dids=dids, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'))
|
|
967
|
+
except UnsupportedOperation as error:
|
|
968
|
+
return generate_http_error_flask(409, error)
|
|
969
|
+
except DataIdentifierNotFound as error:
|
|
970
|
+
return generate_http_error_flask(404, error)
|
|
971
|
+
except AccessDenied as error:
|
|
972
|
+
return generate_http_error_flask(401, error)
|
|
973
|
+
|
|
974
|
+
return '', 200
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
class AttachmentHistory(ErrorHandlingMethodView):
|
|
978
|
+
|
|
979
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
980
|
+
def get(self, scope_name):
|
|
981
|
+
"""
|
|
982
|
+
---
|
|
983
|
+
summary: Get history
|
|
984
|
+
description: Returns the content history of a data identifier.
|
|
985
|
+
tags:
|
|
986
|
+
- Data Identifiers
|
|
987
|
+
parameters:
|
|
988
|
+
- name: scope_name
|
|
989
|
+
in: path
|
|
990
|
+
description: The scope and the name of the did.
|
|
991
|
+
schema:
|
|
992
|
+
type: string
|
|
993
|
+
style: simple
|
|
994
|
+
responses:
|
|
995
|
+
200:
|
|
996
|
+
description: Did found
|
|
997
|
+
content:
|
|
998
|
+
application/x-json-stream:
|
|
999
|
+
schema:
|
|
1000
|
+
description: The dids with their information and history. Elements are separated by new line characters.
|
|
1001
|
+
type: array
|
|
1002
|
+
items:
|
|
1003
|
+
type: object
|
|
1004
|
+
description: A single did with history data.
|
|
1005
|
+
properties:
|
|
1006
|
+
scope:
|
|
1007
|
+
description: The scope of the did.
|
|
1008
|
+
type: string
|
|
1009
|
+
name:
|
|
1010
|
+
description: The name of the did.
|
|
1011
|
+
type: string
|
|
1012
|
+
type:
|
|
1013
|
+
description: The type of the did.
|
|
1014
|
+
type: string
|
|
1015
|
+
bytes:
|
|
1016
|
+
description: The size of the did in bytes.
|
|
1017
|
+
type: integer
|
|
1018
|
+
adler32:
|
|
1019
|
+
description: The abler32 sha checksum.
|
|
1020
|
+
type: string
|
|
1021
|
+
md5:
|
|
1022
|
+
description: The md5 checksum.
|
|
1023
|
+
type: string
|
|
1024
|
+
deleted_at:
|
|
1025
|
+
description: The deleted_at date time.
|
|
1026
|
+
type: string
|
|
1027
|
+
created_at:
|
|
1028
|
+
description: The created_at date time.
|
|
1029
|
+
type: string
|
|
1030
|
+
updated_at:
|
|
1031
|
+
description: The last time the did was updated.
|
|
1032
|
+
type: string
|
|
1033
|
+
401:
|
|
1034
|
+
description: Invalid Auth Token
|
|
1035
|
+
404:
|
|
1036
|
+
description: Did not found
|
|
1037
|
+
406:
|
|
1038
|
+
description: Not acceptable
|
|
1039
|
+
"""
|
|
1040
|
+
try:
|
|
1041
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1042
|
+
|
|
1043
|
+
def generate(vo):
|
|
1044
|
+
for did in list_content_history(scope=scope, name=name, vo=vo):
|
|
1045
|
+
yield render_json(**did) + '\n'
|
|
1046
|
+
|
|
1047
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
1048
|
+
except ValueError as error:
|
|
1049
|
+
return generate_http_error_flask(400, error)
|
|
1050
|
+
except DataIdentifierNotFound as error:
|
|
1051
|
+
return generate_http_error_flask(404, error)
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
class Files(ErrorHandlingMethodView):
|
|
1055
|
+
|
|
1056
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
1057
|
+
def get(self, scope_name):
|
|
1058
|
+
"""
|
|
1059
|
+
---
|
|
1060
|
+
summary: Get replicas
|
|
1061
|
+
description: List all replicas for a did.
|
|
1062
|
+
tags:
|
|
1063
|
+
- Data Identifiers
|
|
1064
|
+
parameters:
|
|
1065
|
+
- name: scope_name
|
|
1066
|
+
in: path
|
|
1067
|
+
description: The scope and the name of the did.
|
|
1068
|
+
schema:
|
|
1069
|
+
type: string
|
|
1070
|
+
style: simple
|
|
1071
|
+
- name: long
|
|
1072
|
+
in: query
|
|
1073
|
+
description: Flag to trigger long output.
|
|
1074
|
+
schema:
|
|
1075
|
+
type: object
|
|
1076
|
+
required: false
|
|
1077
|
+
responses:
|
|
1078
|
+
200:
|
|
1079
|
+
description: OK
|
|
1080
|
+
content:
|
|
1081
|
+
application/x-json-stream:
|
|
1082
|
+
schema:
|
|
1083
|
+
oneOf:
|
|
1084
|
+
- description: All replica information if `long` is defined.
|
|
1085
|
+
type: array
|
|
1086
|
+
items:
|
|
1087
|
+
type: object
|
|
1088
|
+
properties:
|
|
1089
|
+
scope:
|
|
1090
|
+
description: The scope of the did.
|
|
1091
|
+
type: string
|
|
1092
|
+
name:
|
|
1093
|
+
description: The name of the did.
|
|
1094
|
+
type: string
|
|
1095
|
+
bytes:
|
|
1096
|
+
description: The size of the did in bytes.
|
|
1097
|
+
type: integer
|
|
1098
|
+
guid:
|
|
1099
|
+
description: The guid of the did.
|
|
1100
|
+
type: string
|
|
1101
|
+
events:
|
|
1102
|
+
description: The number of events of the did.
|
|
1103
|
+
type: integer
|
|
1104
|
+
adler32:
|
|
1105
|
+
description: The adler32 checksum.
|
|
1106
|
+
type: string
|
|
1107
|
+
lumiblocknr:
|
|
1108
|
+
description: The lumi block nr. Only available if `long` is defined in the query.
|
|
1109
|
+
type: integer
|
|
1110
|
+
- description: All replica information.
|
|
1111
|
+
type: array
|
|
1112
|
+
items:
|
|
1113
|
+
type: object
|
|
1114
|
+
properties:
|
|
1115
|
+
scope:
|
|
1116
|
+
description: The scope of the did.
|
|
1117
|
+
type: string
|
|
1118
|
+
name:
|
|
1119
|
+
description: The name of the did.
|
|
1120
|
+
type: string
|
|
1121
|
+
bytes:
|
|
1122
|
+
description: The size of the did in bytes.
|
|
1123
|
+
type: integer
|
|
1124
|
+
guid:
|
|
1125
|
+
description: The guid of the did.
|
|
1126
|
+
type: string
|
|
1127
|
+
events:
|
|
1128
|
+
description: The number of events of the did.
|
|
1129
|
+
type: integer
|
|
1130
|
+
adler32:
|
|
1131
|
+
description: The adler32 checksum.
|
|
1132
|
+
type: string
|
|
1133
|
+
401:
|
|
1134
|
+
description: Invalid Auth Token
|
|
1135
|
+
404:
|
|
1136
|
+
description: Did not found
|
|
1137
|
+
406:
|
|
1138
|
+
description: Not acceptable
|
|
1139
|
+
"""
|
|
1140
|
+
long = 'long' in request.args
|
|
1141
|
+
|
|
1142
|
+
try:
|
|
1143
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1144
|
+
|
|
1145
|
+
def generate(vo):
|
|
1146
|
+
for file in list_files(scope=scope, name=name, long=long, vo=vo):
|
|
1147
|
+
yield dumps(file) + '\n'
|
|
1148
|
+
|
|
1149
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
1150
|
+
except ValueError as error:
|
|
1151
|
+
return generate_http_error_flask(400, error)
|
|
1152
|
+
except DataIdentifierNotFound as error:
|
|
1153
|
+
return generate_http_error_flask(404, error)
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
class BulkFiles(ErrorHandlingMethodView):
|
|
1157
|
+
|
|
1158
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
1159
|
+
def post(self):
|
|
1160
|
+
"""
|
|
1161
|
+
---
|
|
1162
|
+
summary: List files bulk
|
|
1163
|
+
description: List files in multiple dids
|
|
1164
|
+
tags:
|
|
1165
|
+
- Data Identifiers
|
|
1166
|
+
requestBody:
|
|
1167
|
+
content:
|
|
1168
|
+
application/json:
|
|
1169
|
+
schema:
|
|
1170
|
+
type: array
|
|
1171
|
+
items:
|
|
1172
|
+
description: One did to list files.
|
|
1173
|
+
type: object
|
|
1174
|
+
required:
|
|
1175
|
+
- scope
|
|
1176
|
+
- name
|
|
1177
|
+
properties:
|
|
1178
|
+
scope:
|
|
1179
|
+
description: The did scope.
|
|
1180
|
+
type: string
|
|
1181
|
+
name:
|
|
1182
|
+
description: The did name.
|
|
1183
|
+
type: string
|
|
1184
|
+
responses:
|
|
1185
|
+
201:
|
|
1186
|
+
description: OK
|
|
1187
|
+
content:
|
|
1188
|
+
application/x-json-stream:
|
|
1189
|
+
schema:
|
|
1190
|
+
description: All collections file content.
|
|
1191
|
+
type: array
|
|
1192
|
+
items:
|
|
1193
|
+
description: Collections file content.
|
|
1194
|
+
type: object
|
|
1195
|
+
properties:
|
|
1196
|
+
parent_scope:
|
|
1197
|
+
description: The scope of the parent did.
|
|
1198
|
+
type: string
|
|
1199
|
+
parent_name:
|
|
1200
|
+
description: The name of the parent did.
|
|
1201
|
+
type: string
|
|
1202
|
+
scope:
|
|
1203
|
+
description: The scope of the did.
|
|
1204
|
+
type: string
|
|
1205
|
+
name:
|
|
1206
|
+
description: The name of the did.
|
|
1207
|
+
type: string
|
|
1208
|
+
bytes:
|
|
1209
|
+
description: The size of the did in bytes.
|
|
1210
|
+
type: integer
|
|
1211
|
+
guid:
|
|
1212
|
+
description: The guid of the did.
|
|
1213
|
+
type: string
|
|
1214
|
+
events:
|
|
1215
|
+
description: The number of events of the did.
|
|
1216
|
+
type: integer
|
|
1217
|
+
adler32:
|
|
1218
|
+
description: The adler32 checksum.
|
|
1219
|
+
type: string
|
|
1220
|
+
401:
|
|
1221
|
+
description: Invalid Auth Token
|
|
1222
|
+
"""
|
|
1223
|
+
parameters = json_parameters(parse_response)
|
|
1224
|
+
dids = param_get(parameters, 'dids', default=[])
|
|
1225
|
+
try:
|
|
1226
|
+
def generate(vo):
|
|
1227
|
+
for did in bulk_list_files(dids=dids, vo=vo):
|
|
1228
|
+
yield render_json(**did) + '\n'
|
|
1229
|
+
|
|
1230
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
1231
|
+
except AccessDenied as error:
|
|
1232
|
+
return generate_http_error_flask(401, error)
|
|
1233
|
+
return 'Created', 201
|
|
1234
|
+
|
|
1235
|
+
|
|
1236
|
+
class Parents(ErrorHandlingMethodView):
|
|
1237
|
+
|
|
1238
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
1239
|
+
def get(self, scope_name):
|
|
1240
|
+
"""
|
|
1241
|
+
---
|
|
1242
|
+
summary: Get Parents
|
|
1243
|
+
description: Lists all parents of the did.
|
|
1244
|
+
tags:
|
|
1245
|
+
- Data Identifiers
|
|
1246
|
+
parameters:
|
|
1247
|
+
- name: scope_name
|
|
1248
|
+
in: path
|
|
1249
|
+
description: The scope and the name of the did.
|
|
1250
|
+
schema:
|
|
1251
|
+
type: string
|
|
1252
|
+
style: simple
|
|
1253
|
+
responses:
|
|
1254
|
+
200:
|
|
1255
|
+
description: OK
|
|
1256
|
+
content:
|
|
1257
|
+
application/x-json-stream:
|
|
1258
|
+
schema:
|
|
1259
|
+
description: The parents of the did.
|
|
1260
|
+
type: array
|
|
1261
|
+
items:
|
|
1262
|
+
type: object
|
|
1263
|
+
description: A parent of the did.
|
|
1264
|
+
properties:
|
|
1265
|
+
scope:
|
|
1266
|
+
description: The scope of the did.
|
|
1267
|
+
type: string
|
|
1268
|
+
name:
|
|
1269
|
+
description: The name of the did.
|
|
1270
|
+
type: string
|
|
1271
|
+
type:
|
|
1272
|
+
description: The type of the did.
|
|
1273
|
+
type: string
|
|
1274
|
+
401:
|
|
1275
|
+
description: Invalid Auth Token
|
|
1276
|
+
404:
|
|
1277
|
+
description: Did not found
|
|
1278
|
+
406:
|
|
1279
|
+
description: Not acceptable
|
|
1280
|
+
"""
|
|
1281
|
+
try:
|
|
1282
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1283
|
+
|
|
1284
|
+
def generate(vo):
|
|
1285
|
+
for dataset in list_parent_dids(scope=scope, name=name, vo=vo):
|
|
1286
|
+
yield render_json(**dataset) + "\n"
|
|
1287
|
+
|
|
1288
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
1289
|
+
except ValueError as error:
|
|
1290
|
+
return generate_http_error_flask(400, error)
|
|
1291
|
+
except DataIdentifierNotFound as error:
|
|
1292
|
+
return generate_http_error_flask(404, error)
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
class Meta(ErrorHandlingMethodView):
|
|
1296
|
+
|
|
1297
|
+
@check_accept_header_wrapper_flask(['application/json'])
|
|
1298
|
+
def get(self, scope_name):
|
|
1299
|
+
"""
|
|
1300
|
+
---
|
|
1301
|
+
summary: Get metadata
|
|
1302
|
+
description: Get the metadata of a did.
|
|
1303
|
+
tags:
|
|
1304
|
+
- Data Identifiers
|
|
1305
|
+
parameters:
|
|
1306
|
+
- name: scope_name
|
|
1307
|
+
in: path
|
|
1308
|
+
description: The scope and the name of the did.
|
|
1309
|
+
schema:
|
|
1310
|
+
type: string
|
|
1311
|
+
style: simple
|
|
1312
|
+
- name: plugin
|
|
1313
|
+
in: query
|
|
1314
|
+
description: The plugin to use.
|
|
1315
|
+
schema:
|
|
1316
|
+
type: string
|
|
1317
|
+
default: DID_COLUMN
|
|
1318
|
+
responses:
|
|
1319
|
+
200:
|
|
1320
|
+
description: OK
|
|
1321
|
+
content:
|
|
1322
|
+
application/json:
|
|
1323
|
+
schema:
|
|
1324
|
+
description: A data identifier with all attributes.
|
|
1325
|
+
type: object
|
|
1326
|
+
400:
|
|
1327
|
+
description: Bad Request - Invalid metadata plugin specified
|
|
1328
|
+
401:
|
|
1329
|
+
description: Invalid Auth Token
|
|
1330
|
+
404:
|
|
1331
|
+
description: Did not found
|
|
1332
|
+
406:
|
|
1333
|
+
description: Not acceptable
|
|
1334
|
+
"""
|
|
1335
|
+
try:
|
|
1336
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1337
|
+
except ValueError as error:
|
|
1338
|
+
return generate_http_error_flask(400, error)
|
|
1339
|
+
|
|
1340
|
+
try:
|
|
1341
|
+
plugin = request.args.get('plugin', default='DID_COLUMN')
|
|
1342
|
+
meta = get_metadata(scope=scope, name=name, plugin=plugin, vo=request.environ.get('vo'))
|
|
1343
|
+
return Response(render_json(**meta), content_type='application/json')
|
|
1344
|
+
except DataIdentifierNotFound as error:
|
|
1345
|
+
return generate_http_error_flask(404, error)
|
|
1346
|
+
except UnsupportedMetadataPlugin as error:
|
|
1347
|
+
return generate_http_error_flask(400, error)
|
|
1348
|
+
|
|
1349
|
+
def post(self, scope_name):
|
|
1350
|
+
"""
|
|
1351
|
+
---
|
|
1352
|
+
summary: Add metadata
|
|
1353
|
+
description: Add metadata to a did.
|
|
1354
|
+
tags:
|
|
1355
|
+
- Data Identifiers
|
|
1356
|
+
parameters:
|
|
1357
|
+
- name: scope_name
|
|
1358
|
+
in: path
|
|
1359
|
+
description: The scope and the name of the did.
|
|
1360
|
+
schema:
|
|
1361
|
+
type: string
|
|
1362
|
+
style: simple
|
|
1363
|
+
requestBody:
|
|
1364
|
+
content:
|
|
1365
|
+
'application/json':
|
|
1366
|
+
schema:
|
|
1367
|
+
type: object
|
|
1368
|
+
required:
|
|
1369
|
+
- meta
|
|
1370
|
+
properties:
|
|
1371
|
+
meta:
|
|
1372
|
+
description: The metadata to add. A dictionary containing the metadata name as key and the value as value.
|
|
1373
|
+
type: object
|
|
1374
|
+
recursive:
|
|
1375
|
+
description: Flag if the metadata should be applied recirsively to children.
|
|
1376
|
+
type: boolean
|
|
1377
|
+
default: false
|
|
1378
|
+
responses:
|
|
1379
|
+
201:
|
|
1380
|
+
description: Created
|
|
1381
|
+
content:
|
|
1382
|
+
application/json:
|
|
1383
|
+
schema:
|
|
1384
|
+
type: string
|
|
1385
|
+
enum: ["Created"]
|
|
1386
|
+
401:
|
|
1387
|
+
description: Invalid Auth Token
|
|
1388
|
+
404:
|
|
1389
|
+
description: Not found
|
|
1390
|
+
406:
|
|
1391
|
+
description: Not acceptable
|
|
1392
|
+
"""
|
|
1393
|
+
try:
|
|
1394
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1395
|
+
except ValueError as error:
|
|
1396
|
+
return generate_http_error_flask(400, error)
|
|
1397
|
+
|
|
1398
|
+
parameters = json_parameters()
|
|
1399
|
+
meta = param_get(parameters, 'meta')
|
|
1400
|
+
|
|
1401
|
+
try:
|
|
1402
|
+
set_metadata_bulk(
|
|
1403
|
+
scope=scope,
|
|
1404
|
+
name=name,
|
|
1405
|
+
meta=meta,
|
|
1406
|
+
issuer=request.environ.get('issuer'),
|
|
1407
|
+
recursive=param_get(parameters, 'recursive', default=False),
|
|
1408
|
+
vo=request.environ.get('vo'),
|
|
1409
|
+
)
|
|
1410
|
+
except DataIdentifierNotFound as error:
|
|
1411
|
+
return generate_http_error_flask(404, error)
|
|
1412
|
+
except Duplicate as error:
|
|
1413
|
+
return generate_http_error_flask(409, error)
|
|
1414
|
+
except (KeyNotFound, InvalidMetadata, InvalidValueForKey) as error:
|
|
1415
|
+
return generate_http_error_flask(400, error)
|
|
1416
|
+
|
|
1417
|
+
return "Created", 201
|
|
1418
|
+
|
|
1419
|
+
def delete(self, scope_name):
|
|
1420
|
+
"""
|
|
1421
|
+
---
|
|
1422
|
+
summary: Delete metadata
|
|
1423
|
+
description: Deletes the specified metadata from the did.
|
|
1424
|
+
tags:
|
|
1425
|
+
- Data Identifiers
|
|
1426
|
+
parameters:
|
|
1427
|
+
- name: scope_name
|
|
1428
|
+
in: path
|
|
1429
|
+
description: The scope and the name of the did.
|
|
1430
|
+
schema:
|
|
1431
|
+
type: string
|
|
1432
|
+
style: simple
|
|
1433
|
+
- name: key
|
|
1434
|
+
in: query
|
|
1435
|
+
description: The key to delete.
|
|
1436
|
+
schema:
|
|
1437
|
+
type: string
|
|
1438
|
+
responses:
|
|
1439
|
+
200:
|
|
1440
|
+
description: OK
|
|
1441
|
+
400:
|
|
1442
|
+
description: scope_name could not be parsed.
|
|
1443
|
+
401:
|
|
1444
|
+
description: Invalid Auth Token
|
|
1445
|
+
404:
|
|
1446
|
+
description: Did or key not found
|
|
1447
|
+
406:
|
|
1448
|
+
description: Not acceptable
|
|
1449
|
+
409:
|
|
1450
|
+
description: Feature is not in current database.
|
|
1451
|
+
"""
|
|
1452
|
+
try:
|
|
1453
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1454
|
+
except ValueError as error:
|
|
1455
|
+
return generate_http_error_flask(400, error)
|
|
1456
|
+
|
|
1457
|
+
if 'key' in request.args:
|
|
1458
|
+
key = request.args['key']
|
|
1459
|
+
else:
|
|
1460
|
+
return generate_http_error_flask(404, KeyNotFound.__name__, 'No key provided to remove')
|
|
1461
|
+
|
|
1462
|
+
try:
|
|
1463
|
+
delete_metadata(scope=scope, name=name, key=key, vo=request.environ.get('vo'))
|
|
1464
|
+
except (KeyNotFound, DataIdentifierNotFound) as error:
|
|
1465
|
+
return generate_http_error_flask(404, error)
|
|
1466
|
+
except NotImplementedError as error:
|
|
1467
|
+
return generate_http_error_flask(409, error, 'Feature not in current database')
|
|
1468
|
+
|
|
1469
|
+
return '', 200
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
class SingleMeta(ErrorHandlingMethodView):
|
|
1473
|
+
def post(self, scope_name, key):
|
|
1474
|
+
"""
|
|
1475
|
+
---
|
|
1476
|
+
summary: Add metadata
|
|
1477
|
+
description: Add metadata to a did.
|
|
1478
|
+
tags:
|
|
1479
|
+
- Data Identifiers
|
|
1480
|
+
parameters:
|
|
1481
|
+
- name: scope_name
|
|
1482
|
+
in: path
|
|
1483
|
+
description: The scope and the name of the did.
|
|
1484
|
+
schema:
|
|
1485
|
+
type: string
|
|
1486
|
+
style: simple
|
|
1487
|
+
- name: key
|
|
1488
|
+
in: path
|
|
1489
|
+
description: The key for the metadata.
|
|
1490
|
+
schema:
|
|
1491
|
+
type: string
|
|
1492
|
+
style: simple
|
|
1493
|
+
requestBody:
|
|
1494
|
+
content:
|
|
1495
|
+
'application/json':
|
|
1496
|
+
schema:
|
|
1497
|
+
type: object
|
|
1498
|
+
required:
|
|
1499
|
+
- value
|
|
1500
|
+
properties:
|
|
1501
|
+
value:
|
|
1502
|
+
description: The value to set.
|
|
1503
|
+
type: object
|
|
1504
|
+
responses:
|
|
1505
|
+
201:
|
|
1506
|
+
description: Created
|
|
1507
|
+
content:
|
|
1508
|
+
application/json:
|
|
1509
|
+
schema:
|
|
1510
|
+
type: string
|
|
1511
|
+
enum: ["Created"]
|
|
1512
|
+
401:
|
|
1513
|
+
description: Invalid Auth Token
|
|
1514
|
+
404:
|
|
1515
|
+
description: Did not found
|
|
1516
|
+
406:
|
|
1517
|
+
description: Not acceptable
|
|
1518
|
+
409:
|
|
1519
|
+
description: Metadata already exists
|
|
1520
|
+
400:
|
|
1521
|
+
description: Invalid key or value
|
|
1522
|
+
"""
|
|
1523
|
+
try:
|
|
1524
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1525
|
+
except ValueError as error:
|
|
1526
|
+
return generate_http_error_flask(400, error)
|
|
1527
|
+
|
|
1528
|
+
parameters = json_parameters()
|
|
1529
|
+
value = param_get(parameters, 'value')
|
|
1530
|
+
|
|
1531
|
+
try:
|
|
1532
|
+
set_metadata(
|
|
1533
|
+
scope=scope,
|
|
1534
|
+
name=name,
|
|
1535
|
+
key=key,
|
|
1536
|
+
value=value,
|
|
1537
|
+
issuer=request.environ.get('issuer'),
|
|
1538
|
+
recursive=param_get(parameters, 'recursive', default=False),
|
|
1539
|
+
vo=request.environ.get('vo'),
|
|
1540
|
+
)
|
|
1541
|
+
except DataIdentifierNotFound as error:
|
|
1542
|
+
return generate_http_error_flask(404, error)
|
|
1543
|
+
except Duplicate as error:
|
|
1544
|
+
return generate_http_error_flask(409, error)
|
|
1545
|
+
except (KeyNotFound, InvalidMetadata, InvalidValueForKey) as error:
|
|
1546
|
+
return generate_http_error_flask(400, error)
|
|
1547
|
+
|
|
1548
|
+
return 'Created', 201
|
|
1549
|
+
|
|
1550
|
+
|
|
1551
|
+
class BulkDIDsMeta(ErrorHandlingMethodView):
|
|
1552
|
+
|
|
1553
|
+
def post(self):
|
|
1554
|
+
"""
|
|
1555
|
+
---
|
|
1556
|
+
summary: Add metadata bulk
|
|
1557
|
+
description: Adds metadata in a bulk.
|
|
1558
|
+
tags:
|
|
1559
|
+
- Data Identifiers
|
|
1560
|
+
requestBody:
|
|
1561
|
+
content:
|
|
1562
|
+
'application/json':
|
|
1563
|
+
schema:
|
|
1564
|
+
type: object
|
|
1565
|
+
required:
|
|
1566
|
+
- dids
|
|
1567
|
+
properties:
|
|
1568
|
+
dids:
|
|
1569
|
+
description: A list with all the dids and the metadata.
|
|
1570
|
+
type: array
|
|
1571
|
+
items:
|
|
1572
|
+
description: The did and associated metadata.
|
|
1573
|
+
type: object
|
|
1574
|
+
properties:
|
|
1575
|
+
scope:
|
|
1576
|
+
description: The scope of the did.
|
|
1577
|
+
type: string
|
|
1578
|
+
name:
|
|
1579
|
+
description: The name of the did.
|
|
1580
|
+
type: string
|
|
1581
|
+
meta:
|
|
1582
|
+
description: The metadata to add. A dictionary with the meta key as key and the value as value.
|
|
1583
|
+
type: object
|
|
1584
|
+
responses:
|
|
1585
|
+
200:
|
|
1586
|
+
description: Created
|
|
1587
|
+
content:
|
|
1588
|
+
application/json:
|
|
1589
|
+
schema:
|
|
1590
|
+
type: string
|
|
1591
|
+
enum: ["Created"]
|
|
1592
|
+
401:
|
|
1593
|
+
description: Invalid Auth Token
|
|
1594
|
+
404:
|
|
1595
|
+
description: Did not found
|
|
1596
|
+
406:
|
|
1597
|
+
description: Not acceptable
|
|
1598
|
+
409:
|
|
1599
|
+
description: Unsupported Operation
|
|
1600
|
+
"""
|
|
1601
|
+
parameters = json_parameters()
|
|
1602
|
+
dids = param_get(parameters, 'dids')
|
|
1603
|
+
|
|
1604
|
+
try:
|
|
1605
|
+
set_dids_metadata_bulk(dids=dids, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'))
|
|
1606
|
+
except DataIdentifierNotFound as error:
|
|
1607
|
+
return generate_http_error_flask(404, error)
|
|
1608
|
+
except UnsupportedOperation as error:
|
|
1609
|
+
return generate_http_error_flask(409, error)
|
|
1610
|
+
except AccessDenied as error:
|
|
1611
|
+
return generate_http_error_flask(401, error)
|
|
1612
|
+
|
|
1613
|
+
return 'Created', 201
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
class Rules(ErrorHandlingMethodView):
|
|
1617
|
+
|
|
1618
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
1619
|
+
def get(self, scope_name):
|
|
1620
|
+
"""
|
|
1621
|
+
---
|
|
1622
|
+
summary: Get rules
|
|
1623
|
+
description: Lists all rules of a given did.
|
|
1624
|
+
tags:
|
|
1625
|
+
- Data Identifiers
|
|
1626
|
+
parameters:
|
|
1627
|
+
- name: scope_name
|
|
1628
|
+
in: path
|
|
1629
|
+
description: The scope and the name of the did.
|
|
1630
|
+
schema:
|
|
1631
|
+
type: string
|
|
1632
|
+
style: simple
|
|
1633
|
+
responses:
|
|
1634
|
+
200:
|
|
1635
|
+
description: The rules associated with a did.
|
|
1636
|
+
content:
|
|
1637
|
+
application/x-json-stream:
|
|
1638
|
+
schema:
|
|
1639
|
+
description: The rules associated with a did.
|
|
1640
|
+
type: array
|
|
1641
|
+
items:
|
|
1642
|
+
description: A rule.
|
|
1643
|
+
type: object
|
|
1644
|
+
401:
|
|
1645
|
+
description: Invalid Auth Token
|
|
1646
|
+
404:
|
|
1647
|
+
description: Did or rule not found
|
|
1648
|
+
406:
|
|
1649
|
+
description: Not acceptable
|
|
1650
|
+
"""
|
|
1651
|
+
try:
|
|
1652
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1653
|
+
|
|
1654
|
+
def generate(vo):
|
|
1655
|
+
get_did(scope=scope, name=name, vo=vo)
|
|
1656
|
+
for rule in list_replication_rules({'scope': scope, 'name': name}, vo=vo):
|
|
1657
|
+
yield dumps(rule, cls=APIEncoder) + '\n'
|
|
1658
|
+
|
|
1659
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
1660
|
+
except ValueError as error:
|
|
1661
|
+
return generate_http_error_flask(400, error)
|
|
1662
|
+
except RuleNotFound as error:
|
|
1663
|
+
return generate_http_error_flask(404, error)
|
|
1664
|
+
except DataIdentifierNotFound as error:
|
|
1665
|
+
return generate_http_error_flask(404, error)
|
|
1666
|
+
|
|
1667
|
+
|
|
1668
|
+
class BulkMeta(ErrorHandlingMethodView):
|
|
1669
|
+
|
|
1670
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
1671
|
+
def post(self):
|
|
1672
|
+
"""
|
|
1673
|
+
---
|
|
1674
|
+
summary: Get metadata bulk
|
|
1675
|
+
description: List all metadata of a list of data identifiers.
|
|
1676
|
+
tags:
|
|
1677
|
+
- Data Identifiers
|
|
1678
|
+
requestBody:
|
|
1679
|
+
content:
|
|
1680
|
+
'application/x-json-stream':
|
|
1681
|
+
schema:
|
|
1682
|
+
type: object
|
|
1683
|
+
required:
|
|
1684
|
+
- dids
|
|
1685
|
+
properties:
|
|
1686
|
+
dids:
|
|
1687
|
+
description: The dids.
|
|
1688
|
+
type: array
|
|
1689
|
+
items:
|
|
1690
|
+
description: A did.
|
|
1691
|
+
type: object
|
|
1692
|
+
properties:
|
|
1693
|
+
name:
|
|
1694
|
+
description: The name of the did.
|
|
1695
|
+
type: string
|
|
1696
|
+
scope:
|
|
1697
|
+
description: The scope of the did.
|
|
1698
|
+
type: string
|
|
1699
|
+
inherit:
|
|
1700
|
+
description: Concatenated the metadata of the parent if set to true.
|
|
1701
|
+
type: boolean
|
|
1702
|
+
default: false
|
|
1703
|
+
plugin:
|
|
1704
|
+
description: The did meta plugin to query or "ALL" for all available plugins
|
|
1705
|
+
type: string
|
|
1706
|
+
default: "JSON"
|
|
1707
|
+
responses:
|
|
1708
|
+
200:
|
|
1709
|
+
description: OK
|
|
1710
|
+
content:
|
|
1711
|
+
application/json:
|
|
1712
|
+
schema:
|
|
1713
|
+
description: A list of metadata identifiers for the dids. Separated by new lines.
|
|
1714
|
+
type: array
|
|
1715
|
+
items:
|
|
1716
|
+
description: The metadata for one did.
|
|
1717
|
+
type: object
|
|
1718
|
+
400:
|
|
1719
|
+
description: Cannot decode json parameter list
|
|
1720
|
+
401:
|
|
1721
|
+
description: Invalid Auth Token
|
|
1722
|
+
404:
|
|
1723
|
+
description: Did not found
|
|
1724
|
+
406:
|
|
1725
|
+
description: Not acceptable
|
|
1726
|
+
"""
|
|
1727
|
+
parameters = json_parameters()
|
|
1728
|
+
dids = param_get(parameters, 'dids')
|
|
1729
|
+
inherit = param_get(parameters, 'inherit', default=False)
|
|
1730
|
+
plugin = param_get(parameters, 'plugin', default='JSON')
|
|
1731
|
+
|
|
1732
|
+
try:
|
|
1733
|
+
def generate(vo):
|
|
1734
|
+
for meta in get_metadata_bulk(dids, inherit=inherit, plugin=plugin, vo=vo):
|
|
1735
|
+
yield render_json(**meta) + '\n'
|
|
1736
|
+
|
|
1737
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
1738
|
+
except ValueError as error:
|
|
1739
|
+
return generate_http_error_flask(400, error, 'Cannot decode json parameter list')
|
|
1740
|
+
except DataIdentifierNotFound as error:
|
|
1741
|
+
return generate_http_error_flask(404, error)
|
|
1742
|
+
|
|
1743
|
+
|
|
1744
|
+
class AssociatedRules(ErrorHandlingMethodView):
|
|
1745
|
+
|
|
1746
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
1747
|
+
def get(self, scope_name):
|
|
1748
|
+
"""
|
|
1749
|
+
---
|
|
1750
|
+
summary: Get associated rules
|
|
1751
|
+
description: Gets all associated rules for a file.
|
|
1752
|
+
tags:
|
|
1753
|
+
- Data Identifiers
|
|
1754
|
+
parameters:
|
|
1755
|
+
- name: scope_name
|
|
1756
|
+
in: path
|
|
1757
|
+
description: The scope and the name of the did.
|
|
1758
|
+
schema:
|
|
1759
|
+
type: string
|
|
1760
|
+
style: simple
|
|
1761
|
+
responses:
|
|
1762
|
+
200:
|
|
1763
|
+
description: OK
|
|
1764
|
+
content:
|
|
1765
|
+
application/x-json-stream:
|
|
1766
|
+
schema:
|
|
1767
|
+
description: All associated rules for a file. Items are separated by new line character.
|
|
1768
|
+
type: array
|
|
1769
|
+
items:
|
|
1770
|
+
description: A replication rule associated with the file. Has more fields than listed here.
|
|
1771
|
+
type: object
|
|
1772
|
+
properties:
|
|
1773
|
+
id:
|
|
1774
|
+
description: The id of the rule.
|
|
1775
|
+
type: string
|
|
1776
|
+
subscription_id:
|
|
1777
|
+
description: The subscription id of the rule.
|
|
1778
|
+
type: string
|
|
1779
|
+
account:
|
|
1780
|
+
description: The account associated with the rule.
|
|
1781
|
+
type: string
|
|
1782
|
+
scope:
|
|
1783
|
+
description: The scope associated with the rule.
|
|
1784
|
+
type: string
|
|
1785
|
+
name:
|
|
1786
|
+
description: The name of the rule.
|
|
1787
|
+
type: string
|
|
1788
|
+
state:
|
|
1789
|
+
description: The state of the rule.
|
|
1790
|
+
type: string
|
|
1791
|
+
rse_expression:
|
|
1792
|
+
description: The rse expression of the rule.
|
|
1793
|
+
type: string
|
|
1794
|
+
401:
|
|
1795
|
+
description: Invalid Auth Token
|
|
1796
|
+
404:
|
|
1797
|
+
description: Did not found
|
|
1798
|
+
406:
|
|
1799
|
+
description: Not acceptable
|
|
1800
|
+
"""
|
|
1801
|
+
try:
|
|
1802
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
1803
|
+
|
|
1804
|
+
def generate(vo):
|
|
1805
|
+
for rule in list_associated_replication_rules_for_file(scope=scope, name=name, vo=vo):
|
|
1806
|
+
yield dumps(rule, cls=APIEncoder) + '\n'
|
|
1807
|
+
|
|
1808
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
1809
|
+
except ValueError as error:
|
|
1810
|
+
return generate_http_error_flask(400, error)
|
|
1811
|
+
except DataIdentifierNotFound as error:
|
|
1812
|
+
return generate_http_error_flask(404, error)
|
|
1813
|
+
|
|
1814
|
+
|
|
1815
|
+
class GUIDLookup(ErrorHandlingMethodView):
|
|
1816
|
+
|
|
1817
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
1818
|
+
def get(self, guid):
|
|
1819
|
+
"""
|
|
1820
|
+
---
|
|
1821
|
+
summary: Get dataset
|
|
1822
|
+
description: Returns the dataset associated with a GUID.
|
|
1823
|
+
tags:
|
|
1824
|
+
- Data Identifiers
|
|
1825
|
+
parameters:
|
|
1826
|
+
- name: guid
|
|
1827
|
+
in: path
|
|
1828
|
+
description: The GUID to query buy.
|
|
1829
|
+
schema:
|
|
1830
|
+
type: string
|
|
1831
|
+
style: simple
|
|
1832
|
+
responses:
|
|
1833
|
+
200:
|
|
1834
|
+
description: OK
|
|
1835
|
+
content:
|
|
1836
|
+
application/x-json-stream:
|
|
1837
|
+
schema:
|
|
1838
|
+
description: A list of all datasets associated with the guid. Items are separated by new line character.
|
|
1839
|
+
type: array
|
|
1840
|
+
items:
|
|
1841
|
+
description: A dataset associated with a guid.
|
|
1842
|
+
type: object
|
|
1843
|
+
properties:
|
|
1844
|
+
scope:
|
|
1845
|
+
description: The scope of the dataset.
|
|
1846
|
+
type: string
|
|
1847
|
+
name:
|
|
1848
|
+
description: The name of the dataset.
|
|
1849
|
+
type: string
|
|
1850
|
+
401:
|
|
1851
|
+
description: Invalid Auth Token
|
|
1852
|
+
404:
|
|
1853
|
+
description: Did not found
|
|
1854
|
+
406:
|
|
1855
|
+
description: Not acceptable
|
|
1856
|
+
"""
|
|
1857
|
+
try:
|
|
1858
|
+
def generate(vo):
|
|
1859
|
+
for dataset in get_dataset_by_guid(guid, vo=vo):
|
|
1860
|
+
yield dumps(dataset, cls=APIEncoder) + '\n'
|
|
1861
|
+
|
|
1862
|
+
return try_stream(generate(vo=request.environ.get('vo')))
|
|
1863
|
+
except DataIdentifierNotFound as error:
|
|
1864
|
+
return generate_http_error_flask(404, error)
|
|
1865
|
+
|
|
1866
|
+
|
|
1867
|
+
class SampleLegacy(ErrorHandlingMethodView):
|
|
1868
|
+
|
|
1869
|
+
def post(self, input_scope, input_name, output_scope, output_name, nbfiles):
|
|
1870
|
+
"""
|
|
1871
|
+
---
|
|
1872
|
+
summary: Create sample
|
|
1873
|
+
description: Creates a sample from an input collection.
|
|
1874
|
+
tags:
|
|
1875
|
+
- Data Identifiers
|
|
1876
|
+
parameters:
|
|
1877
|
+
- name: input_scope
|
|
1878
|
+
in: path
|
|
1879
|
+
description: The input scope.
|
|
1880
|
+
schema:
|
|
1881
|
+
type: string
|
|
1882
|
+
style: simple
|
|
1883
|
+
- name: input_name
|
|
1884
|
+
in: path
|
|
1885
|
+
description: The input name.
|
|
1886
|
+
schema:
|
|
1887
|
+
type: string
|
|
1888
|
+
style: simple
|
|
1889
|
+
- name: output_scope
|
|
1890
|
+
in: path
|
|
1891
|
+
description: The output scope.
|
|
1892
|
+
schema:
|
|
1893
|
+
type: string
|
|
1894
|
+
style: simple
|
|
1895
|
+
- name: output_name
|
|
1896
|
+
in: path
|
|
1897
|
+
description: The output name.
|
|
1898
|
+
schema:
|
|
1899
|
+
type: string
|
|
1900
|
+
style: simple
|
|
1901
|
+
- name: nbfiles
|
|
1902
|
+
in: path
|
|
1903
|
+
description: The number of files to register in the output dataset.
|
|
1904
|
+
schema:
|
|
1905
|
+
type: string
|
|
1906
|
+
style: simple
|
|
1907
|
+
responses:
|
|
1908
|
+
201:
|
|
1909
|
+
description: OK
|
|
1910
|
+
content:
|
|
1911
|
+
application/json:
|
|
1912
|
+
schema:
|
|
1913
|
+
type: string
|
|
1914
|
+
enum: ["Created"]
|
|
1915
|
+
401:
|
|
1916
|
+
description: Invalid Auth Token
|
|
1917
|
+
404:
|
|
1918
|
+
description: Not found
|
|
1919
|
+
406:
|
|
1920
|
+
description: Not acceptable
|
|
1921
|
+
409:
|
|
1922
|
+
description: Duplication
|
|
1923
|
+
"""
|
|
1924
|
+
try:
|
|
1925
|
+
create_did_sample(
|
|
1926
|
+
input_scope=input_scope,
|
|
1927
|
+
input_name=input_name,
|
|
1928
|
+
output_scope=output_scope,
|
|
1929
|
+
output_name=output_name,
|
|
1930
|
+
issuer=request.environ.get('issuer'),
|
|
1931
|
+
nbfiles=nbfiles,
|
|
1932
|
+
vo=request.environ.get('vo'),
|
|
1933
|
+
)
|
|
1934
|
+
except DataIdentifierNotFound as error:
|
|
1935
|
+
return generate_http_error_flask(404, error)
|
|
1936
|
+
except (DuplicateContent, DataIdentifierAlreadyExists, UnsupportedOperation) as error:
|
|
1937
|
+
return generate_http_error_flask(409, error)
|
|
1938
|
+
except AccessDenied as error:
|
|
1939
|
+
return generate_http_error_flask(401, error)
|
|
1940
|
+
|
|
1941
|
+
return 'Created', 201
|
|
1942
|
+
|
|
1943
|
+
|
|
1944
|
+
class Sample(ErrorHandlingMethodView):
|
|
1945
|
+
|
|
1946
|
+
def post(self):
|
|
1947
|
+
"""
|
|
1948
|
+
---
|
|
1949
|
+
summary: Create sample
|
|
1950
|
+
description: Creates a sample from an input collection.
|
|
1951
|
+
tags:
|
|
1952
|
+
- Data Identifiers
|
|
1953
|
+
requestBody:
|
|
1954
|
+
description: Parameters (source and destination) for the files in the sample to be created
|
|
1955
|
+
content:
|
|
1956
|
+
'application/json':
|
|
1957
|
+
schema:
|
|
1958
|
+
type: object
|
|
1959
|
+
required:
|
|
1960
|
+
- input_scope
|
|
1961
|
+
- input_name
|
|
1962
|
+
- output_scope
|
|
1963
|
+
- output_name
|
|
1964
|
+
- nbfiles
|
|
1965
|
+
properties:
|
|
1966
|
+
input_scope:
|
|
1967
|
+
description: The input scope.
|
|
1968
|
+
type: string
|
|
1969
|
+
input_name:
|
|
1970
|
+
description: The input name.
|
|
1971
|
+
type: string
|
|
1972
|
+
output_scope:
|
|
1973
|
+
description: The output scope.
|
|
1974
|
+
type: string
|
|
1975
|
+
output_name:
|
|
1976
|
+
description: The output name.
|
|
1977
|
+
type: string
|
|
1978
|
+
nbfiles:
|
|
1979
|
+
description: The number of files to register in the output dataset.
|
|
1980
|
+
type: string
|
|
1981
|
+
responses:
|
|
1982
|
+
201:
|
|
1983
|
+
description: OK
|
|
1984
|
+
content:
|
|
1985
|
+
application/json:
|
|
1986
|
+
schema:
|
|
1987
|
+
type: string
|
|
1988
|
+
enum: ["Created"]
|
|
1989
|
+
401:
|
|
1990
|
+
description: Invalid Auth Token
|
|
1991
|
+
404:
|
|
1992
|
+
description: Not found
|
|
1993
|
+
406:
|
|
1994
|
+
description: Not acceptable
|
|
1995
|
+
409:
|
|
1996
|
+
description: Duplication
|
|
1997
|
+
"""
|
|
1998
|
+
parameters = json_parameters()
|
|
1999
|
+
try:
|
|
2000
|
+
create_did_sample(
|
|
2001
|
+
input_scope=parameters['input_scope'],
|
|
2002
|
+
input_name=parameters['input_name'],
|
|
2003
|
+
output_scope=parameters['output_scope'],
|
|
2004
|
+
output_name=parameters['output_name'],
|
|
2005
|
+
issuer=request.environ.get('issuer'),
|
|
2006
|
+
nbfiles=parameters['nbfiles'],
|
|
2007
|
+
vo=request.environ.get('vo'),
|
|
2008
|
+
)
|
|
2009
|
+
except DataIdentifierNotFound as error:
|
|
2010
|
+
return generate_http_error_flask(404, error)
|
|
2011
|
+
except (DuplicateContent, DataIdentifierAlreadyExists, UnsupportedOperation) as error:
|
|
2012
|
+
return generate_http_error_flask(409, error)
|
|
2013
|
+
except AccessDenied as error:
|
|
2014
|
+
return generate_http_error_flask(401, error)
|
|
2015
|
+
|
|
2016
|
+
return 'Created', 201
|
|
2017
|
+
|
|
2018
|
+
|
|
2019
|
+
class NewDIDs(ErrorHandlingMethodView):
|
|
2020
|
+
|
|
2021
|
+
@check_accept_header_wrapper_flask(['application/x-json-stream'])
|
|
2022
|
+
def get(self):
|
|
2023
|
+
"""
|
|
2024
|
+
---
|
|
2025
|
+
summary: Get recent identifiers
|
|
2026
|
+
description: Returns a list of recent identifiers.
|
|
2027
|
+
tags:
|
|
2028
|
+
- Data Identifiers
|
|
2029
|
+
parameters:
|
|
2030
|
+
- name: type
|
|
2031
|
+
in: query
|
|
2032
|
+
description: The type of the did.
|
|
2033
|
+
schema:
|
|
2034
|
+
type: string
|
|
2035
|
+
required: false
|
|
2036
|
+
responses:
|
|
2037
|
+
200:
|
|
2038
|
+
description: OK
|
|
2039
|
+
content:
|
|
2040
|
+
application/x-json-stream:
|
|
2041
|
+
schema:
|
|
2042
|
+
description: A list of the recent dids. Items are separated by new line characters.
|
|
2043
|
+
type: array
|
|
2044
|
+
items:
|
|
2045
|
+
description: A did.
|
|
2046
|
+
type: object
|
|
2047
|
+
properties:
|
|
2048
|
+
scope:
|
|
2049
|
+
description: The scope of the did.
|
|
2050
|
+
type: string
|
|
2051
|
+
name:
|
|
2052
|
+
description: The name of the did.
|
|
2053
|
+
type: string
|
|
2054
|
+
did_type:
|
|
2055
|
+
description: The type of the did.
|
|
2056
|
+
type: string
|
|
2057
|
+
401:
|
|
2058
|
+
description: Invalid Auth Token
|
|
2059
|
+
406:
|
|
2060
|
+
description: Not acceptable
|
|
2061
|
+
"""
|
|
2062
|
+
def generate(_type, vo):
|
|
2063
|
+
for did in list_new_dids(did_type=_type, vo=vo):
|
|
2064
|
+
yield dumps(did, cls=APIEncoder) + '\n'
|
|
2065
|
+
|
|
2066
|
+
type_param = request.args.get('type', default=None)
|
|
2067
|
+
|
|
2068
|
+
return try_stream(generate(_type=type_param, vo=request.environ.get('vo')))
|
|
2069
|
+
|
|
2070
|
+
|
|
2071
|
+
class Resurrect(ErrorHandlingMethodView):
|
|
2072
|
+
|
|
2073
|
+
def post(self):
|
|
2074
|
+
"""
|
|
2075
|
+
---
|
|
2076
|
+
summary: Resurrect dids
|
|
2077
|
+
description: Resurrect all given dids.
|
|
2078
|
+
tags:
|
|
2079
|
+
- Data Identifiers
|
|
2080
|
+
requestBody:
|
|
2081
|
+
content:
|
|
2082
|
+
'application/json':
|
|
2083
|
+
schema:
|
|
2084
|
+
description: List of did to resurrect.
|
|
2085
|
+
type: array
|
|
2086
|
+
items:
|
|
2087
|
+
description: A did to resurrect.
|
|
2088
|
+
type: object
|
|
2089
|
+
properties:
|
|
2090
|
+
scope:
|
|
2091
|
+
description: The scope of the did.
|
|
2092
|
+
type: string
|
|
2093
|
+
name:
|
|
2094
|
+
description: The name of the did
|
|
2095
|
+
type: string
|
|
2096
|
+
responses:
|
|
2097
|
+
201:
|
|
2098
|
+
description: OK
|
|
2099
|
+
content:
|
|
2100
|
+
application/json:
|
|
2101
|
+
schema:
|
|
2102
|
+
type: string
|
|
2103
|
+
enum: ["Created"]
|
|
2104
|
+
401:
|
|
2105
|
+
description: Invalid Auth Token
|
|
2106
|
+
404:
|
|
2107
|
+
description: Not found
|
|
2108
|
+
409:
|
|
2109
|
+
description: Conflict
|
|
2110
|
+
500:
|
|
2111
|
+
description: Internal error
|
|
2112
|
+
"""
|
|
2113
|
+
dids = json_list()
|
|
2114
|
+
|
|
2115
|
+
try:
|
|
2116
|
+
resurrect(dids=dids, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'))
|
|
2117
|
+
except DataIdentifierNotFound as error:
|
|
2118
|
+
return generate_http_error_flask(404, error)
|
|
2119
|
+
except (DuplicateContent, DataIdentifierAlreadyExists, UnsupportedOperation) as error:
|
|
2120
|
+
return generate_http_error_flask(409, error)
|
|
2121
|
+
except AccessDenied as error:
|
|
2122
|
+
return generate_http_error_flask(401, error)
|
|
2123
|
+
return 'Created', 201
|
|
2124
|
+
|
|
2125
|
+
|
|
2126
|
+
class Follow(ErrorHandlingMethodView):
|
|
2127
|
+
|
|
2128
|
+
@check_accept_header_wrapper_flask(['application/json'])
|
|
2129
|
+
def get(self, scope_name):
|
|
2130
|
+
"""
|
|
2131
|
+
---
|
|
2132
|
+
summary: Get followers
|
|
2133
|
+
description: Get all followers for a specific did.
|
|
2134
|
+
tags:
|
|
2135
|
+
- Data Identifiers
|
|
2136
|
+
parameters:
|
|
2137
|
+
- name: scope_name
|
|
2138
|
+
in: path
|
|
2139
|
+
description: The scope and the name of the did.
|
|
2140
|
+
schema:
|
|
2141
|
+
type: string
|
|
2142
|
+
style: simple
|
|
2143
|
+
responses:
|
|
2144
|
+
200:
|
|
2145
|
+
description: OK
|
|
2146
|
+
content:
|
|
2147
|
+
application/json:
|
|
2148
|
+
schema:
|
|
2149
|
+
description: A list of all followers of a did.
|
|
2150
|
+
type: array
|
|
2151
|
+
items:
|
|
2152
|
+
description: A follower of a did.
|
|
2153
|
+
type: object
|
|
2154
|
+
properties:
|
|
2155
|
+
user:
|
|
2156
|
+
description: The user which follows the did.
|
|
2157
|
+
type: string
|
|
2158
|
+
400:
|
|
2159
|
+
description: Value error
|
|
2160
|
+
401:
|
|
2161
|
+
description: Invalid Auth Token
|
|
2162
|
+
404:
|
|
2163
|
+
description: Did not found
|
|
2164
|
+
406:
|
|
2165
|
+
description: Not acceptable
|
|
2166
|
+
"""
|
|
2167
|
+
try:
|
|
2168
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
2169
|
+
|
|
2170
|
+
def generate(vo):
|
|
2171
|
+
for user in get_users_following_did(scope=scope, name=name, vo=vo):
|
|
2172
|
+
yield render_json(**user) + '\n'
|
|
2173
|
+
|
|
2174
|
+
return try_stream(generate(vo=request.environ.get('vo')), content_type='application/json')
|
|
2175
|
+
except ValueError as error:
|
|
2176
|
+
return generate_http_error_flask(400, error)
|
|
2177
|
+
except DataIdentifierNotFound as error:
|
|
2178
|
+
return generate_http_error_flask(404, error)
|
|
2179
|
+
|
|
2180
|
+
def post(self, scope_name):
|
|
2181
|
+
"""
|
|
2182
|
+
---
|
|
2183
|
+
summary: Post follow
|
|
2184
|
+
description: Mark the input DID as being followed by the given account.
|
|
2185
|
+
tags:
|
|
2186
|
+
- Data Identifiers
|
|
2187
|
+
parameters:
|
|
2188
|
+
- name: scope_name
|
|
2189
|
+
in: path
|
|
2190
|
+
description: The scope and the name of the did.
|
|
2191
|
+
schema:
|
|
2192
|
+
type: string
|
|
2193
|
+
style: simple
|
|
2194
|
+
requestBody:
|
|
2195
|
+
content:
|
|
2196
|
+
application/json:
|
|
2197
|
+
schema:
|
|
2198
|
+
type: object
|
|
2199
|
+
required:
|
|
2200
|
+
- account
|
|
2201
|
+
properties:
|
|
2202
|
+
account:
|
|
2203
|
+
description: The account to follow the did.
|
|
2204
|
+
type: string
|
|
2205
|
+
responses:
|
|
2206
|
+
201:
|
|
2207
|
+
description: OK
|
|
2208
|
+
400:
|
|
2209
|
+
description: Scope or name could not be interpreted
|
|
2210
|
+
401:
|
|
2211
|
+
description: Invalid Auth Token
|
|
2212
|
+
404:
|
|
2213
|
+
description: Not found
|
|
2214
|
+
500:
|
|
2215
|
+
description: Internal error
|
|
2216
|
+
"""
|
|
2217
|
+
try:
|
|
2218
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
2219
|
+
except ValueError as error:
|
|
2220
|
+
return generate_http_error_flask(400, error)
|
|
2221
|
+
|
|
2222
|
+
parameters = json_parameters()
|
|
2223
|
+
account = param_get(parameters, 'account')
|
|
2224
|
+
|
|
2225
|
+
try:
|
|
2226
|
+
add_did_to_followed(scope=scope, name=name, account=account, vo=request.environ.get('vo'))
|
|
2227
|
+
except DataIdentifierNotFound as error:
|
|
2228
|
+
return generate_http_error_flask(404, error)
|
|
2229
|
+
except AccessDenied as error:
|
|
2230
|
+
return generate_http_error_flask(401, error)
|
|
2231
|
+
|
|
2232
|
+
def delete(self, scope_name):
|
|
2233
|
+
"""
|
|
2234
|
+
---
|
|
2235
|
+
summary: Delete follow
|
|
2236
|
+
description: Mark the input DID as not followed
|
|
2237
|
+
tags:
|
|
2238
|
+
- Data Identifiers
|
|
2239
|
+
parameters:
|
|
2240
|
+
- name: scope_name
|
|
2241
|
+
in: path
|
|
2242
|
+
description: The scope and the name of the did.
|
|
2243
|
+
schema:
|
|
2244
|
+
type: string
|
|
2245
|
+
style: simple
|
|
2246
|
+
requestBody:
|
|
2247
|
+
content:
|
|
2248
|
+
'application/json':
|
|
2249
|
+
schema:
|
|
2250
|
+
type: object
|
|
2251
|
+
required:
|
|
2252
|
+
- account
|
|
2253
|
+
properties:
|
|
2254
|
+
account:
|
|
2255
|
+
description: The account to unfollow the did.
|
|
2256
|
+
type: string
|
|
2257
|
+
responses:
|
|
2258
|
+
200:
|
|
2259
|
+
description: OK
|
|
2260
|
+
401:
|
|
2261
|
+
description: Invalid Auth Token
|
|
2262
|
+
404:
|
|
2263
|
+
description: Not found
|
|
2264
|
+
500:
|
|
2265
|
+
description: Internal error
|
|
2266
|
+
"""
|
|
2267
|
+
try:
|
|
2268
|
+
scope, name = parse_scope_name(scope_name, request.environ.get('vo'))
|
|
2269
|
+
except ValueError as error:
|
|
2270
|
+
return generate_http_error_flask(400, error)
|
|
2271
|
+
|
|
2272
|
+
parameters = json_parameters()
|
|
2273
|
+
account = param_get(parameters, 'account')
|
|
2274
|
+
|
|
2275
|
+
try:
|
|
2276
|
+
remove_did_from_followed(scope=scope, name=name, account=account, issuer=request.environ.get('issuer'), vo=request.environ.get('vo'))
|
|
2277
|
+
except DataIdentifierNotFound as error:
|
|
2278
|
+
return generate_http_error_flask(404, error)
|
|
2279
|
+
|
|
2280
|
+
return '', 200
|
|
2281
|
+
|
|
2282
|
+
|
|
2283
|
+
def blueprint():
|
|
2284
|
+
bp = AuthenticatedBlueprint('dids', __name__, url_prefix='/dids')
|
|
2285
|
+
|
|
2286
|
+
scope_view = Scope.as_view('scope')
|
|
2287
|
+
bp.add_url_rule('/<scope>/', view_func=scope_view, methods=['get', ])
|
|
2288
|
+
guid_lookup_view = GUIDLookup.as_view('guid_lookup')
|
|
2289
|
+
bp.add_url_rule('/<guid>/guid', view_func=guid_lookup_view, methods=['get', ])
|
|
2290
|
+
search_view = Search.as_view('search')
|
|
2291
|
+
bp.add_url_rule('/<scope>/dids/search', view_func=search_view, methods=['get', ])
|
|
2292
|
+
dids_view = DIDs.as_view('dids')
|
|
2293
|
+
bp.add_url_rule('/<path:scope_name>/status', view_func=dids_view, methods=['put', 'get'])
|
|
2294
|
+
files_view = Files.as_view('files')
|
|
2295
|
+
bp.add_url_rule('/<path:scope_name>/files', view_func=files_view, methods=['get', ])
|
|
2296
|
+
attachment_history_view = AttachmentHistory.as_view('attachment_history')
|
|
2297
|
+
bp.add_url_rule('/<path:scope_name>/dids/history', view_func=attachment_history_view, methods=['get', ])
|
|
2298
|
+
attachment_view = Attachment.as_view('attachment')
|
|
2299
|
+
bp.add_url_rule('/<path:scope_name>/dids', view_func=attachment_view, methods=['get', 'post', 'delete'])
|
|
2300
|
+
meta_view = Meta.as_view('meta')
|
|
2301
|
+
bp.add_url_rule('/<path:scope_name>/meta', view_func=meta_view, methods=['get', 'post', 'delete'])
|
|
2302
|
+
singlemeta_view = SingleMeta.as_view('singlemeta')
|
|
2303
|
+
bp.add_url_rule('/<path:scope_name>/meta/<key>', view_func=singlemeta_view, methods=['post', ])
|
|
2304
|
+
bulkdidsmeta_view = BulkDIDsMeta.as_view('bulkdidsmeta')
|
|
2305
|
+
bp.add_url_rule('/bulkdidsmeta', view_func=bulkdidsmeta_view, methods=['post', ])
|
|
2306
|
+
rules_view = Rules.as_view('rules')
|
|
2307
|
+
bp.add_url_rule('/<path:scope_name>/rules', view_func=rules_view, methods=['get', ])
|
|
2308
|
+
parents_view = Parents.as_view('parents')
|
|
2309
|
+
bp.add_url_rule('/<path:scope_name>/parents', view_func=parents_view, methods=['get', ])
|
|
2310
|
+
associated_rules_view = AssociatedRules.as_view('associated_rules')
|
|
2311
|
+
bp.add_url_rule('/<path:scope_name>/associated_rules', view_func=associated_rules_view, methods=['get', ])
|
|
2312
|
+
follow_view = Follow.as_view('follow')
|
|
2313
|
+
bp.add_url_rule('/<path:scope_name>/follow', view_func=follow_view, methods=['get', 'post', 'delete'])
|
|
2314
|
+
bp.add_url_rule('/<path:scope_name>', view_func=dids_view, methods=['get', 'post'])
|
|
2315
|
+
bulkdids_view = BulkDIDS.as_view('bulkdids')
|
|
2316
|
+
bp.add_url_rule('', view_func=bulkdids_view, methods=['post', ])
|
|
2317
|
+
sample_view_legacy = SampleLegacy.as_view('sample')
|
|
2318
|
+
bp.add_url_rule('/<input_scope>/<input_name>/<output_scope>/<output_name>/<nbfiles>/sample', view_func=sample_view_legacy, methods=['post', ])
|
|
2319
|
+
sample_view = Sample.as_view('sample_new')
|
|
2320
|
+
bp.add_url_rule('/sample', view_func=sample_view, methods=['post', ])
|
|
2321
|
+
attachements_view = Attachments.as_view('attachments')
|
|
2322
|
+
bp.add_url_rule('/attachments', view_func=attachements_view, methods=['post', ])
|
|
2323
|
+
new_dids_view = NewDIDs.as_view('new_dids')
|
|
2324
|
+
bp.add_url_rule('/new', view_func=new_dids_view, methods=['get', ])
|
|
2325
|
+
resurrect_view = Resurrect.as_view('resurrect')
|
|
2326
|
+
bp.add_url_rule('/resurrect', view_func=resurrect_view, methods=['post', ])
|
|
2327
|
+
bulkmeta_view = BulkMeta.as_view('bulkmeta')
|
|
2328
|
+
bp.add_url_rule('/bulkmeta', view_func=bulkmeta_view, methods=['post', ])
|
|
2329
|
+
files_view = BulkFiles.as_view('bulkfiles')
|
|
2330
|
+
bp.add_url_rule('/bulkfiles', view_func=files_view, methods=['post', ])
|
|
2331
|
+
|
|
2332
|
+
bp.after_request(response_headers)
|
|
2333
|
+
return bp
|
|
2334
|
+
|
|
2335
|
+
|
|
2336
|
+
def make_doc():
|
|
2337
|
+
""" Only used for sphinx documentation """
|
|
2338
|
+
doc_app = Flask(__name__)
|
|
2339
|
+
doc_app.register_blueprint(blueprint())
|
|
2340
|
+
return doc_app
|