rucio 32.8.6__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 +18 -0
- rucio/alembicrevision.py +16 -0
- rucio/api/__init__.py +14 -0
- rucio/api/account.py +266 -0
- rucio/api/account_limit.py +287 -0
- rucio/api/authentication.py +302 -0
- rucio/api/config.py +218 -0
- rucio/api/credential.py +60 -0
- rucio/api/did.py +726 -0
- rucio/api/dirac.py +71 -0
- rucio/api/exporter.py +60 -0
- rucio/api/heartbeat.py +62 -0
- rucio/api/identity.py +160 -0
- rucio/api/importer.py +46 -0
- rucio/api/lifetime_exception.py +95 -0
- rucio/api/lock.py +131 -0
- rucio/api/meta.py +85 -0
- rucio/api/permission.py +72 -0
- rucio/api/quarantined_replica.py +69 -0
- rucio/api/replica.py +528 -0
- rucio/api/request.py +220 -0
- rucio/api/rse.py +601 -0
- rucio/api/rule.py +335 -0
- rucio/api/scope.py +89 -0
- rucio/api/subscription.py +255 -0
- rucio/api/temporary_did.py +49 -0
- rucio/api/vo.py +112 -0
- rucio/client/__init__.py +16 -0
- rucio/client/accountclient.py +413 -0
- rucio/client/accountlimitclient.py +155 -0
- rucio/client/baseclient.py +929 -0
- rucio/client/client.py +77 -0
- rucio/client/configclient.py +113 -0
- rucio/client/credentialclient.py +54 -0
- rucio/client/didclient.py +691 -0
- rucio/client/diracclient.py +48 -0
- rucio/client/downloadclient.py +1674 -0
- rucio/client/exportclient.py +44 -0
- rucio/client/fileclient.py +51 -0
- rucio/client/importclient.py +42 -0
- rucio/client/lifetimeclient.py +74 -0
- rucio/client/lockclient.py +99 -0
- rucio/client/metaclient.py +137 -0
- rucio/client/pingclient.py +45 -0
- rucio/client/replicaclient.py +444 -0
- rucio/client/requestclient.py +109 -0
- rucio/client/rseclient.py +664 -0
- rucio/client/ruleclient.py +287 -0
- rucio/client/scopeclient.py +88 -0
- rucio/client/subscriptionclient.py +161 -0
- rucio/client/touchclient.py +78 -0
- rucio/client/uploadclient.py +871 -0
- rucio/common/__init__.py +14 -0
- rucio/common/cache.py +74 -0
- rucio/common/config.py +796 -0
- rucio/common/constants.py +92 -0
- rucio/common/constraints.py +18 -0
- rucio/common/didtype.py +187 -0
- rucio/common/dumper/__init__.py +306 -0
- rucio/common/dumper/consistency.py +449 -0
- rucio/common/dumper/data_models.py +325 -0
- rucio/common/dumper/path_parsing.py +65 -0
- rucio/common/exception.py +1092 -0
- rucio/common/extra.py +37 -0
- rucio/common/logging.py +404 -0
- rucio/common/pcache.py +1387 -0
- rucio/common/policy.py +84 -0
- rucio/common/schema/__init__.py +143 -0
- rucio/common/schema/atlas.py +411 -0
- rucio/common/schema/belleii.py +406 -0
- rucio/common/schema/cms.py +478 -0
- rucio/common/schema/domatpc.py +399 -0
- rucio/common/schema/escape.py +424 -0
- rucio/common/schema/generic.py +431 -0
- rucio/common/schema/generic_multi_vo.py +410 -0
- rucio/common/schema/icecube.py +404 -0
- rucio/common/schema/lsst.py +423 -0
- rucio/common/stomp_utils.py +160 -0
- rucio/common/stopwatch.py +56 -0
- rucio/common/test_rucio_server.py +148 -0
- rucio/common/types.py +158 -0
- rucio/common/utils.py +1946 -0
- rucio/core/__init__.py +14 -0
- rucio/core/account.py +426 -0
- rucio/core/account_counter.py +171 -0
- rucio/core/account_limit.py +357 -0
- rucio/core/authentication.py +563 -0
- rucio/core/config.py +386 -0
- rucio/core/credential.py +218 -0
- rucio/core/did.py +3102 -0
- rucio/core/did_meta_plugins/__init__.py +250 -0
- rucio/core/did_meta_plugins/did_column_meta.py +326 -0
- rucio/core/did_meta_plugins/did_meta_plugin_interface.py +116 -0
- rucio/core/did_meta_plugins/filter_engine.py +573 -0
- rucio/core/did_meta_plugins/json_meta.py +215 -0
- rucio/core/did_meta_plugins/mongo_meta.py +199 -0
- rucio/core/did_meta_plugins/postgres_meta.py +317 -0
- rucio/core/dirac.py +208 -0
- rucio/core/distance.py +164 -0
- rucio/core/exporter.py +59 -0
- rucio/core/heartbeat.py +263 -0
- rucio/core/identity.py +290 -0
- rucio/core/importer.py +248 -0
- rucio/core/lifetime_exception.py +377 -0
- rucio/core/lock.py +474 -0
- rucio/core/message.py +241 -0
- rucio/core/meta.py +190 -0
- rucio/core/monitor.py +441 -0
- rucio/core/naming_convention.py +154 -0
- rucio/core/nongrid_trace.py +124 -0
- rucio/core/oidc.py +1339 -0
- rucio/core/permission/__init__.py +107 -0
- rucio/core/permission/atlas.py +1333 -0
- rucio/core/permission/belleii.py +1076 -0
- rucio/core/permission/cms.py +1166 -0
- rucio/core/permission/escape.py +1076 -0
- rucio/core/permission/generic.py +1128 -0
- rucio/core/permission/generic_multi_vo.py +1148 -0
- rucio/core/quarantined_replica.py +190 -0
- rucio/core/replica.py +3627 -0
- rucio/core/replica_sorter.py +368 -0
- rucio/core/request.py +2241 -0
- rucio/core/rse.py +1835 -0
- rucio/core/rse_counter.py +155 -0
- rucio/core/rse_expression_parser.py +460 -0
- rucio/core/rse_selector.py +277 -0
- rucio/core/rule.py +3419 -0
- rucio/core/rule_grouping.py +1473 -0
- rucio/core/scope.py +152 -0
- rucio/core/subscription.py +316 -0
- rucio/core/temporary_did.py +188 -0
- rucio/core/topology.py +448 -0
- rucio/core/trace.py +361 -0
- rucio/core/transfer.py +1233 -0
- rucio/core/vo.py +151 -0
- rucio/core/volatile_replica.py +123 -0
- rucio/daemons/__init__.py +14 -0
- rucio/daemons/abacus/__init__.py +14 -0
- rucio/daemons/abacus/account.py +106 -0
- rucio/daemons/abacus/collection_replica.py +113 -0
- rucio/daemons/abacus/rse.py +107 -0
- rucio/daemons/atropos/__init__.py +14 -0
- rucio/daemons/atropos/atropos.py +243 -0
- rucio/daemons/auditor/__init__.py +261 -0
- rucio/daemons/auditor/hdfs.py +86 -0
- rucio/daemons/auditor/srmdumps.py +284 -0
- rucio/daemons/automatix/__init__.py +14 -0
- rucio/daemons/automatix/automatix.py +281 -0
- rucio/daemons/badreplicas/__init__.py +14 -0
- rucio/daemons/badreplicas/minos.py +311 -0
- rucio/daemons/badreplicas/minos_temporary_expiration.py +173 -0
- rucio/daemons/badreplicas/necromancer.py +200 -0
- rucio/daemons/bb8/__init__.py +14 -0
- rucio/daemons/bb8/bb8.py +356 -0
- rucio/daemons/bb8/common.py +762 -0
- rucio/daemons/bb8/nuclei_background_rebalance.py +147 -0
- rucio/daemons/bb8/t2_background_rebalance.py +146 -0
- rucio/daemons/c3po/__init__.py +14 -0
- rucio/daemons/c3po/algorithms/__init__.py +14 -0
- rucio/daemons/c3po/algorithms/simple.py +131 -0
- rucio/daemons/c3po/algorithms/t2_free_space.py +125 -0
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +127 -0
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +279 -0
- rucio/daemons/c3po/c3po.py +342 -0
- rucio/daemons/c3po/collectors/__init__.py +14 -0
- rucio/daemons/c3po/collectors/agis.py +108 -0
- rucio/daemons/c3po/collectors/free_space.py +62 -0
- rucio/daemons/c3po/collectors/jedi_did.py +48 -0
- rucio/daemons/c3po/collectors/mock_did.py +46 -0
- rucio/daemons/c3po/collectors/network_metrics.py +63 -0
- rucio/daemons/c3po/collectors/workload.py +110 -0
- rucio/daemons/c3po/utils/__init__.py +14 -0
- rucio/daemons/c3po/utils/dataset_cache.py +40 -0
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +45 -0
- rucio/daemons/c3po/utils/expiring_list.py +63 -0
- rucio/daemons/c3po/utils/popularity.py +82 -0
- rucio/daemons/c3po/utils/timeseries.py +76 -0
- rucio/daemons/cache/__init__.py +14 -0
- rucio/daemons/cache/consumer.py +191 -0
- rucio/daemons/common.py +391 -0
- rucio/daemons/conveyor/__init__.py +14 -0
- rucio/daemons/conveyor/common.py +530 -0
- rucio/daemons/conveyor/finisher.py +492 -0
- rucio/daemons/conveyor/poller.py +372 -0
- rucio/daemons/conveyor/preparer.py +198 -0
- rucio/daemons/conveyor/receiver.py +206 -0
- rucio/daemons/conveyor/stager.py +127 -0
- rucio/daemons/conveyor/submitter.py +379 -0
- rucio/daemons/conveyor/throttler.py +468 -0
- rucio/daemons/follower/__init__.py +14 -0
- rucio/daemons/follower/follower.py +97 -0
- rucio/daemons/hermes/__init__.py +14 -0
- rucio/daemons/hermes/hermes.py +738 -0
- rucio/daemons/judge/__init__.py +14 -0
- rucio/daemons/judge/cleaner.py +149 -0
- rucio/daemons/judge/evaluator.py +172 -0
- rucio/daemons/judge/injector.py +154 -0
- rucio/daemons/judge/repairer.py +144 -0
- rucio/daemons/oauthmanager/__init__.py +14 -0
- rucio/daemons/oauthmanager/oauthmanager.py +199 -0
- rucio/daemons/reaper/__init__.py +14 -0
- rucio/daemons/reaper/dark_reaper.py +272 -0
- rucio/daemons/reaper/light_reaper.py +255 -0
- rucio/daemons/reaper/reaper.py +701 -0
- rucio/daemons/replicarecoverer/__init__.py +14 -0
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +487 -0
- rucio/daemons/storage/__init__.py +14 -0
- rucio/daemons/storage/consistency/__init__.py +14 -0
- rucio/daemons/storage/consistency/actions.py +753 -0
- rucio/daemons/tracer/__init__.py +14 -0
- rucio/daemons/tracer/kronos.py +513 -0
- rucio/daemons/transmogrifier/__init__.py +14 -0
- rucio/daemons/transmogrifier/transmogrifier.py +753 -0
- rucio/daemons/undertaker/__init__.py +14 -0
- rucio/daemons/undertaker/undertaker.py +137 -0
- rucio/db/__init__.py +14 -0
- rucio/db/sqla/__init__.py +38 -0
- rucio/db/sqla/constants.py +192 -0
- rucio/db/sqla/migrate_repo/__init__.py +14 -0
- rucio/db/sqla/migrate_repo/env.py +111 -0
- rucio/db/sqla/migrate_repo/versions/01eaf73ab656_add_new_rule_notification_state_progress.py +71 -0
- rucio/db/sqla/migrate_repo/versions/0437a40dbfd1_add_eol_at_in_rules.py +50 -0
- rucio/db/sqla/migrate_repo/versions/0f1adb7a599a_create_transfer_hops_table.py +61 -0
- rucio/db/sqla/migrate_repo/versions/102efcf145f4_added_stuck_at_column_to_rules.py +46 -0
- rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +93 -0
- rucio/db/sqla/migrate_repo/versions/140fef722e91_cleanup_distances_table.py +78 -0
- rucio/db/sqla/migrate_repo/versions/14ec5aeb64cf_add_request_external_host.py +46 -0
- rucio/db/sqla/migrate_repo/versions/156fb5b5a14_add_request_type_to_requests_idx.py +53 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +69 -0
- rucio/db/sqla/migrate_repo/versions/16a0aca82e12_create_index_on_table_replicas_path.py +42 -0
- rucio/db/sqla/migrate_repo/versions/1803333ac20f_adding_provenance_and_phys_group.py +46 -0
- rucio/db/sqla/migrate_repo/versions/1a29d6a9504c_add_didtype_chck_to_requests.py +61 -0
- rucio/db/sqla/migrate_repo/versions/1a80adff031a_create_index_on_rules_hist_recent.py +42 -0
- rucio/db/sqla/migrate_repo/versions/1c45d9730ca6_increase_identity_length.py +141 -0
- rucio/db/sqla/migrate_repo/versions/1d1215494e95_add_quarantined_replicas_table.py +75 -0
- rucio/db/sqla/migrate_repo/versions/1d96f484df21_asynchronous_rules_and_rule_approval.py +75 -0
- rucio/db/sqla/migrate_repo/versions/1f46c5f240ac_add_bytes_column_to_bad_replicas.py +46 -0
- rucio/db/sqla/migrate_repo/versions/1fc15ab60d43_add_message_history_table.py +51 -0
- rucio/db/sqla/migrate_repo/versions/2190e703eb6e_move_rse_settings_to_rse_attributes.py +135 -0
- rucio/db/sqla/migrate_repo/versions/21d6b9dc9961_add_mismatch_scheme_state_to_requests.py +65 -0
- rucio/db/sqla/migrate_repo/versions/22cf51430c78_add_availability_column_to_table_rses.py +42 -0
- rucio/db/sqla/migrate_repo/versions/22d887e4ec0a_create_sources_table.py +66 -0
- rucio/db/sqla/migrate_repo/versions/25821a8a45a3_remove_unique_constraint_on_requests.py +54 -0
- rucio/db/sqla/migrate_repo/versions/25fc855625cf_added_unique_constraint_to_rules.py +43 -0
- rucio/db/sqla/migrate_repo/versions/269fee20dee9_add_repair_cnt_to_locks.py +46 -0
- rucio/db/sqla/migrate_repo/versions/271a46ea6244_add_ignore_availability_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/277b5fbb41d3_switch_heartbeats_executable.py +54 -0
- rucio/db/sqla/migrate_repo/versions/27e3a68927fb_remove_replicas_tombstone_and_replicas_.py +39 -0
- rucio/db/sqla/migrate_repo/versions/2854cd9e168_added_rule_id_column.py +48 -0
- rucio/db/sqla/migrate_repo/versions/295289b5a800_processed_by_and__at_in_requests.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2962ece31cf4_add_nbaccesses_column_in_the_did_table.py +48 -0
- rucio/db/sqla/migrate_repo/versions/2af3291ec4c_added_replicas_history_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/2b69addda658_add_columns_for_third_party_copy_read_.py +47 -0
- rucio/db/sqla/migrate_repo/versions/2b8e7bcb4783_add_config_table.py +72 -0
- rucio/db/sqla/migrate_repo/versions/2ba5229cb54c_add_submitted_at_to_requests_table.py +46 -0
- rucio/db/sqla/migrate_repo/versions/2cbee484dcf9_added_column_volume_to_rse_transfer_.py +45 -0
- rucio/db/sqla/migrate_repo/versions/2edee4a83846_add_source_to_requests_and_requests_.py +48 -0
- rucio/db/sqla/migrate_repo/versions/2eef46be23d4_change_tokens_pk.py +48 -0
- rucio/db/sqla/migrate_repo/versions/2f648fc909f3_index_in_rule_history_on_scope_name.py +42 -0
- rucio/db/sqla/migrate_repo/versions/3082b8cef557_add_naming_convention_table_and_closed_.py +69 -0
- rucio/db/sqla/migrate_repo/versions/30fa38b6434e_add_index_on_service_column_in_the_message_table.py +46 -0
- rucio/db/sqla/migrate_repo/versions/3152492b110b_added_staging_area_column.py +78 -0
- rucio/db/sqla/migrate_repo/versions/32c7d2783f7e_create_bad_replicas_table.py +62 -0
- rucio/db/sqla/migrate_repo/versions/3345511706b8_replicas_table_pk_definition_is_in_.py +74 -0
- rucio/db/sqla/migrate_repo/versions/35ef10d1e11b_change_index_on_table_requests.py +44 -0
- rucio/db/sqla/migrate_repo/versions/379a19b5332d_create_rse_limits_table.py +67 -0
- rucio/db/sqla/migrate_repo/versions/384b96aa0f60_created_rule_history_tables.py +134 -0
- rucio/db/sqla/migrate_repo/versions/3ac1660a1a72_extend_distance_table.py +58 -0
- rucio/db/sqla/migrate_repo/versions/3ad36e2268b0_create_collection_replicas_updates_table.py +79 -0
- rucio/db/sqla/migrate_repo/versions/3c9df354071b_extend_waiting_request_state.py +61 -0
- rucio/db/sqla/migrate_repo/versions/3d9813fab443_add_a_new_state_lost_in_badfilesstatus.py +45 -0
- rucio/db/sqla/migrate_repo/versions/40ad39ce3160_add_transferred_at_to_requests_table.py +46 -0
- rucio/db/sqla/migrate_repo/versions/4207be2fd914_add_notification_column_to_rules.py +65 -0
- rucio/db/sqla/migrate_repo/versions/42db2617c364_create_index_on_requests_external_id.py +42 -0
- rucio/db/sqla/migrate_repo/versions/436827b13f82_added_column_activity_to_table_requests.py +46 -0
- rucio/db/sqla/migrate_repo/versions/44278720f774_update_requests_typ_sta_upd_idx_index.py +46 -0
- rucio/db/sqla/migrate_repo/versions/45378a1e76a8_create_collection_replica_table.py +80 -0
- rucio/db/sqla/migrate_repo/versions/469d262be19_removing_created_at_index.py +43 -0
- rucio/db/sqla/migrate_repo/versions/4783c1f49cb4_create_distance_table.py +61 -0
- rucio/db/sqla/migrate_repo/versions/49a21b4d4357_create_index_on_table_tokens.py +47 -0
- rucio/db/sqla/migrate_repo/versions/4a2cbedda8b9_add_source_replica_expression_column_to_.py +46 -0
- rucio/db/sqla/migrate_repo/versions/4a7182d9578b_added_bytes_length_accessed_at_columns.py +52 -0
- rucio/db/sqla/migrate_repo/versions/4bab9edd01fc_create_index_on_requests_rule_id.py +42 -0
- rucio/db/sqla/migrate_repo/versions/4c3a4acfe006_new_attr_account_table.py +65 -0
- rucio/db/sqla/migrate_repo/versions/4cf0a2e127d4_adding_transient_metadata.py +46 -0
- rucio/db/sqla/migrate_repo/versions/50280c53117c_add_qos_class_to_rse.py +47 -0
- rucio/db/sqla/migrate_repo/versions/52153819589c_add_rse_id_to_replicas_table.py +45 -0
- rucio/db/sqla/migrate_repo/versions/52fd9f4916fa_added_activity_to_rules.py +46 -0
- rucio/db/sqla/migrate_repo/versions/53b479c3cb0f_fix_did_meta_table_missing_updated_at_.py +48 -0
- rucio/db/sqla/migrate_repo/versions/5673b4b6e843_add_wfms_metadata_to_rule_tables.py +50 -0
- rucio/db/sqla/migrate_repo/versions/575767d9f89_added_source_history_table.py +59 -0
- rucio/db/sqla/migrate_repo/versions/58bff7008037_add_started_at_to_requests.py +48 -0
- rucio/db/sqla/migrate_repo/versions/58c8b78301ab_rename_callback_to_message.py +108 -0
- rucio/db/sqla/migrate_repo/versions/5f139f77382a_added_child_rule_id_column.py +57 -0
- rucio/db/sqla/migrate_repo/versions/688ef1840840_adding_did_meta_table.py +51 -0
- rucio/db/sqla/migrate_repo/versions/6e572a9bfbf3_add_new_split_container_column_to_rules.py +50 -0
- rucio/db/sqla/migrate_repo/versions/70587619328_add_comment_column_for_subscriptions.py +46 -0
- rucio/db/sqla/migrate_repo/versions/739064d31565_remove_history_table_pks.py +42 -0
- rucio/db/sqla/migrate_repo/versions/7541902bf173_add_didsfollowed_and_followevents_table.py +93 -0
- rucio/db/sqla/migrate_repo/versions/7ec22226cdbf_new_replica_state_for_temporary_.py +73 -0
- rucio/db/sqla/migrate_repo/versions/810a41685bc1_added_columns_rse_transfer_limits.py +52 -0
- rucio/db/sqla/migrate_repo/versions/83f991c63a93_correct_rse_expression_length.py +45 -0
- rucio/db/sqla/migrate_repo/versions/8523998e2e76_increase_size_of_extended_attributes_.py +46 -0
- rucio/db/sqla/migrate_repo/versions/8ea9122275b1_adding_missing_function_based_indices.py +54 -0
- rucio/db/sqla/migrate_repo/versions/90f47792bb76_add_clob_payload_to_messages.py +48 -0
- rucio/db/sqla/migrate_repo/versions/914b8f02df38_new_table_for_lifetime_model_exceptions.py +70 -0
- rucio/db/sqla/migrate_repo/versions/94a5961ddbf2_add_estimator_columns.py +48 -0
- rucio/db/sqla/migrate_repo/versions/9a1b149a2044_add_saml_identity_type.py +95 -0
- rucio/db/sqla/migrate_repo/versions/9a45bc4ea66d_add_vp_table.py +55 -0
- rucio/db/sqla/migrate_repo/versions/9eb936a81eb1_true_is_true.py +74 -0
- rucio/db/sqla/migrate_repo/versions/a118956323f8_added_vo_table_and_vo_col_to_rse.py +78 -0
- rucio/db/sqla/migrate_repo/versions/a193a275255c_add_status_column_in_messages.py +49 -0
- rucio/db/sqla/migrate_repo/versions/a5f6f6e928a7_1_7_0.py +124 -0
- rucio/db/sqla/migrate_repo/versions/a616581ee47_added_columns_to_table_requests.py +60 -0
- rucio/db/sqla/migrate_repo/versions/a6eb23955c28_state_idx_non_functional.py +53 -0
- rucio/db/sqla/migrate_repo/versions/a74275a1ad30_added_global_quota_table.py +56 -0
- rucio/db/sqla/migrate_repo/versions/a93e4e47bda_heartbeats.py +67 -0
- rucio/db/sqla/migrate_repo/versions/ae2a56fcc89_added_comment_column_to_rules.py +50 -0
- rucio/db/sqla/migrate_repo/versions/b4293a99f344_added_column_identity_to_table_tokens.py +46 -0
- rucio/db/sqla/migrate_repo/versions/b7d287de34fd_removal_of_replicastate_source.py +92 -0
- rucio/db/sqla/migrate_repo/versions/b818052fa670_add_index_to_quarantined_replicas.py +42 -0
- rucio/db/sqla/migrate_repo/versions/b8caac94d7f0_add_comments_column_for_subscriptions_.py +46 -0
- rucio/db/sqla/migrate_repo/versions/b96a1c7e1cc4_new_bad_pfns_table_and_bad_replicas_.py +147 -0
- rucio/db/sqla/migrate_repo/versions/bb695f45c04_extend_request_state.py +78 -0
- rucio/db/sqla/migrate_repo/versions/bc68e9946deb_add_staging_timestamps_to_request.py +53 -0
- rucio/db/sqla/migrate_repo/versions/bf3baa1c1474_correct_pk_and_idx_for_history_tables.py +74 -0
- rucio/db/sqla/migrate_repo/versions/c0937668555f_add_qos_policy_map_table.py +56 -0
- rucio/db/sqla/migrate_repo/versions/c129ccdb2d5_add_lumiblocknr_to_dids.py +46 -0
- rucio/db/sqla/migrate_repo/versions/ccdbcd48206e_add_did_type_column_index_on_did_meta_.py +68 -0
- rucio/db/sqla/migrate_repo/versions/cebad904c4dd_new_payload_column_for_heartbeats.py +48 -0
- rucio/db/sqla/migrate_repo/versions/d1189a09c6e0_oauth2_0_and_jwt_feature_support_adding_.py +149 -0
- rucio/db/sqla/migrate_repo/versions/d23453595260_extend_request_state_for_preparer.py +106 -0
- rucio/db/sqla/migrate_repo/versions/d6dceb1de2d_added_purge_column_to_rules.py +47 -0
- rucio/db/sqla/migrate_repo/versions/d6e2c3b2cf26_remove_third_party_copy_column_from_rse.py +45 -0
- rucio/db/sqla/migrate_repo/versions/d91002c5841_new_account_limits_table.py +105 -0
- rucio/db/sqla/migrate_repo/versions/e138c364ebd0_extending_columns_for_filter_and_.py +52 -0
- rucio/db/sqla/migrate_repo/versions/e59300c8b179_support_for_archive.py +106 -0
- rucio/db/sqla/migrate_repo/versions/f1b14a8c2ac1_postgres_use_check_constraints.py +30 -0
- rucio/db/sqla/migrate_repo/versions/f41ffe206f37_oracle_global_temporary_tables.py +75 -0
- rucio/db/sqla/migrate_repo/versions/f85a2962b021_adding_transfertool_column_to_requests_.py +49 -0
- rucio/db/sqla/migrate_repo/versions/fa7a7d78b602_increase_refresh_token_size.py +45 -0
- rucio/db/sqla/migrate_repo/versions/fb28a95fe288_add_replicas_rse_id_tombstone_idx.py +38 -0
- rucio/db/sqla/migrate_repo/versions/fe1a65b176c9_set_third_party_copy_read_and_write_.py +44 -0
- rucio/db/sqla/migrate_repo/versions/fe8ea2fa9788_added_third_party_copy_column_to_rse_.py +46 -0
- rucio/db/sqla/models.py +1834 -0
- rucio/db/sqla/sautils.py +48 -0
- rucio/db/sqla/session.py +470 -0
- rucio/db/sqla/types.py +207 -0
- rucio/db/sqla/util.py +521 -0
- rucio/rse/__init__.py +97 -0
- rucio/rse/protocols/__init__.py +14 -0
- rucio/rse/protocols/cache.py +123 -0
- rucio/rse/protocols/dummy.py +112 -0
- rucio/rse/protocols/gfal.py +701 -0
- rucio/rse/protocols/globus.py +243 -0
- rucio/rse/protocols/gsiftp.py +93 -0
- rucio/rse/protocols/http_cache.py +83 -0
- rucio/rse/protocols/mock.py +124 -0
- rucio/rse/protocols/ngarc.py +210 -0
- rucio/rse/protocols/posix.py +251 -0
- rucio/rse/protocols/protocol.py +530 -0
- rucio/rse/protocols/rclone.py +365 -0
- rucio/rse/protocols/rfio.py +137 -0
- rucio/rse/protocols/srm.py +339 -0
- rucio/rse/protocols/ssh.py +414 -0
- rucio/rse/protocols/storm.py +207 -0
- rucio/rse/protocols/webdav.py +547 -0
- rucio/rse/protocols/xrootd.py +295 -0
- rucio/rse/rsemanager.py +752 -0
- rucio/tests/__init__.py +14 -0
- rucio/tests/common.py +244 -0
- rucio/tests/common_server.py +132 -0
- rucio/transfertool/__init__.py +14 -0
- rucio/transfertool/fts3.py +1484 -0
- rucio/transfertool/globus.py +200 -0
- rucio/transfertool/globus_library.py +182 -0
- rucio/transfertool/mock.py +81 -0
- rucio/transfertool/transfertool.py +212 -0
- rucio/vcsversion.py +11 -0
- rucio/version.py +46 -0
- rucio/web/__init__.py +14 -0
- rucio/web/rest/__init__.py +14 -0
- rucio/web/rest/flaskapi/__init__.py +14 -0
- rucio/web/rest/flaskapi/authenticated_bp.py +28 -0
- rucio/web/rest/flaskapi/v1/__init__.py +14 -0
- rucio/web/rest/flaskapi/v1/accountlimits.py +234 -0
- rucio/web/rest/flaskapi/v1/accounts.py +1088 -0
- rucio/web/rest/flaskapi/v1/archives.py +100 -0
- rucio/web/rest/flaskapi/v1/auth.py +1642 -0
- rucio/web/rest/flaskapi/v1/common.py +385 -0
- rucio/web/rest/flaskapi/v1/config.py +305 -0
- rucio/web/rest/flaskapi/v1/credentials.py +213 -0
- rucio/web/rest/flaskapi/v1/dids.py +2204 -0
- rucio/web/rest/flaskapi/v1/dirac.py +116 -0
- rucio/web/rest/flaskapi/v1/export.py +77 -0
- rucio/web/rest/flaskapi/v1/heartbeats.py +129 -0
- rucio/web/rest/flaskapi/v1/identities.py +263 -0
- rucio/web/rest/flaskapi/v1/import.py +133 -0
- rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +315 -0
- rucio/web/rest/flaskapi/v1/locks.py +360 -0
- rucio/web/rest/flaskapi/v1/main.py +83 -0
- rucio/web/rest/flaskapi/v1/meta.py +226 -0
- rucio/web/rest/flaskapi/v1/metrics.py +37 -0
- rucio/web/rest/flaskapi/v1/nongrid_traces.py +97 -0
- rucio/web/rest/flaskapi/v1/ping.py +89 -0
- rucio/web/rest/flaskapi/v1/redirect.py +366 -0
- rucio/web/rest/flaskapi/v1/replicas.py +1866 -0
- rucio/web/rest/flaskapi/v1/requests.py +841 -0
- rucio/web/rest/flaskapi/v1/rses.py +2204 -0
- rucio/web/rest/flaskapi/v1/rules.py +824 -0
- rucio/web/rest/flaskapi/v1/scopes.py +161 -0
- rucio/web/rest/flaskapi/v1/subscriptions.py +646 -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/tmp_dids.py +115 -0
- rucio/web/rest/flaskapi/v1/traces.py +100 -0
- rucio/web/rest/flaskapi/v1/vos.py +280 -0
- rucio/web/rest/main.py +19 -0
- rucio/web/rest/metrics.py +28 -0
- rucio-32.8.6.data/data/rucio/etc/alembic.ini.template +71 -0
- rucio-32.8.6.data/data/rucio/etc/alembic_offline.ini.template +74 -0
- rucio-32.8.6.data/data/rucio/etc/globus-config.yml.template +5 -0
- rucio-32.8.6.data/data/rucio/etc/ldap.cfg.template +30 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approval_request.tmpl +38 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +4 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_approved_user.tmpl +17 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +6 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_denied_user.tmpl +17 -0
- rucio-32.8.6.data/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +19 -0
- rucio-32.8.6.data/data/rucio/etc/rse-accounts.cfg.template +25 -0
- rucio-32.8.6.data/data/rucio/etc/rucio.cfg.atlas.client.template +42 -0
- rucio-32.8.6.data/data/rucio/etc/rucio.cfg.template +257 -0
- rucio-32.8.6.data/data/rucio/etc/rucio_multi_vo.cfg.template +234 -0
- rucio-32.8.6.data/data/rucio/requirements.txt +55 -0
- rucio-32.8.6.data/data/rucio/tools/bootstrap.py +34 -0
- rucio-32.8.6.data/data/rucio/tools/merge_rucio_configs.py +147 -0
- rucio-32.8.6.data/data/rucio/tools/reset_database.py +40 -0
- rucio-32.8.6.data/scripts/rucio +2540 -0
- rucio-32.8.6.data/scripts/rucio-abacus-account +75 -0
- rucio-32.8.6.data/scripts/rucio-abacus-collection-replica +47 -0
- rucio-32.8.6.data/scripts/rucio-abacus-rse +79 -0
- rucio-32.8.6.data/scripts/rucio-admin +2434 -0
- rucio-32.8.6.data/scripts/rucio-atropos +61 -0
- rucio-32.8.6.data/scripts/rucio-auditor +199 -0
- rucio-32.8.6.data/scripts/rucio-automatix +51 -0
- rucio-32.8.6.data/scripts/rucio-bb8 +58 -0
- rucio-32.8.6.data/scripts/rucio-c3po +86 -0
- rucio-32.8.6.data/scripts/rucio-cache-client +135 -0
- rucio-32.8.6.data/scripts/rucio-cache-consumer +43 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-finisher +59 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-poller +67 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-preparer +38 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-receiver +44 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-stager +77 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-submitter +140 -0
- rucio-32.8.6.data/scripts/rucio-conveyor-throttler +105 -0
- rucio-32.8.6.data/scripts/rucio-dark-reaper +54 -0
- rucio-32.8.6.data/scripts/rucio-dumper +159 -0
- rucio-32.8.6.data/scripts/rucio-follower +45 -0
- rucio-32.8.6.data/scripts/rucio-hermes +55 -0
- rucio-32.8.6.data/scripts/rucio-judge-cleaner +90 -0
- rucio-32.8.6.data/scripts/rucio-judge-evaluator +138 -0
- rucio-32.8.6.data/scripts/rucio-judge-injector +45 -0
- rucio-32.8.6.data/scripts/rucio-judge-repairer +45 -0
- rucio-32.8.6.data/scripts/rucio-kronos +45 -0
- rucio-32.8.6.data/scripts/rucio-light-reaper +53 -0
- rucio-32.8.6.data/scripts/rucio-minos +54 -0
- rucio-32.8.6.data/scripts/rucio-minos-temporary-expiration +51 -0
- rucio-32.8.6.data/scripts/rucio-necromancer +121 -0
- rucio-32.8.6.data/scripts/rucio-oauth-manager +64 -0
- rucio-32.8.6.data/scripts/rucio-reaper +84 -0
- rucio-32.8.6.data/scripts/rucio-replica-recoverer +249 -0
- rucio-32.8.6.data/scripts/rucio-storage-consistency-actions +75 -0
- rucio-32.8.6.data/scripts/rucio-transmogrifier +78 -0
- rucio-32.8.6.data/scripts/rucio-undertaker +77 -0
- rucio-32.8.6.dist-info/METADATA +83 -0
- rucio-32.8.6.dist-info/RECORD +481 -0
- rucio-32.8.6.dist-info/WHEEL +5 -0
- rucio-32.8.6.dist-info/licenses/AUTHORS.rst +94 -0
- rucio-32.8.6.dist-info/licenses/LICENSE +201 -0
- rucio-32.8.6.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import enum
|
|
17
|
+
from collections import namedtuple
|
|
18
|
+
|
|
19
|
+
from rucio.common.config import config_get_bool
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
Constants.
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
RESERVED_KEYS = ['scope', 'name', 'account', 'did_type', 'is_open', 'monotonic', 'obsolete', 'complete',
|
|
27
|
+
'availability', 'suppressed', 'bytes', 'length', 'md5', 'adler32', 'rule_evaluation_action',
|
|
28
|
+
'rule_evaluation_required', 'expired_at', 'deleted_at', 'created_at', 'updated_at']
|
|
29
|
+
# collection_keys =
|
|
30
|
+
# file_keys =
|
|
31
|
+
|
|
32
|
+
KEY_TYPES = ['ALL', 'COLLECTION', 'FILE', 'DERIVED']
|
|
33
|
+
# all(container, dataset, file), collection(dataset or container), file, derived(compute from file for collection)
|
|
34
|
+
|
|
35
|
+
SCHEME_MAP = {'srm': ['srm', 'gsiftp'],
|
|
36
|
+
'gsiftp': ['srm', 'gsiftp'],
|
|
37
|
+
'https': ['https', 'davs', 'srm+https', 'cs3s'],
|
|
38
|
+
'davs': ['https', 'davs', 'srm+https', 'cs3s'],
|
|
39
|
+
'srm+https': ['https', 'davs', 'srm+https', 'cs3s'],
|
|
40
|
+
'cs3s': ['https', 'davs', 'srm+https', 'cs3s'],
|
|
41
|
+
'root': ['root'],
|
|
42
|
+
'scp': ['scp'],
|
|
43
|
+
'rsync': ['rsync'],
|
|
44
|
+
'rclone': ['rclone']}
|
|
45
|
+
if config_get_bool('transfers', 'srm_https_compatibility', raise_exception=False, default=False):
|
|
46
|
+
SCHEME_MAP['srm'].append('https')
|
|
47
|
+
SCHEME_MAP['https'].append('srm')
|
|
48
|
+
SCHEME_MAP['srm'].append('davs')
|
|
49
|
+
SCHEME_MAP['davs'].append('srm')
|
|
50
|
+
|
|
51
|
+
SUPPORTED_PROTOCOLS = ['gsiftp', 'srm', 'root', 'davs', 'http', 'https', 'file', 'storm', 'srm+https', 'scp', 'rsync', 'rclone']
|
|
52
|
+
|
|
53
|
+
FTS_STATE = namedtuple('FTS_STATE', ['SUBMITTED', 'READY', 'ACTIVE', 'FAILED', 'FINISHED', 'FINISHEDDIRTY', 'NOT_USED',
|
|
54
|
+
'CANCELED'])('SUBMITTED', 'READY', 'ACTIVE', 'FAILED', 'FINISHED', 'FINISHEDDIRTY',
|
|
55
|
+
'NOT_USED', 'CANCELED')
|
|
56
|
+
|
|
57
|
+
FTS_COMPLETE_STATE = namedtuple('FTS_COMPLETE_STATE', ['OK', 'ERROR'])('Ok', 'Error')
|
|
58
|
+
|
|
59
|
+
# https://gitlab.cern.ch/fts/fts3/-/blob/master/src/db/generic/Job.h#L41
|
|
60
|
+
FTS_JOB_TYPE = namedtuple('FTS_JOB_TYPE', ['MULTIPLE_REPLICA', 'MULTI_HOP', 'SESSION_REUSE', 'REGULAR'])('R', 'H', 'Y', 'N')
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Messages constants
|
|
64
|
+
|
|
65
|
+
MAX_MESSAGE_LENGTH = 4000
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class SuspiciousAvailability(enum.Enum):
|
|
69
|
+
ALL = 0
|
|
70
|
+
EXIST_COPIES = 1
|
|
71
|
+
LAST_COPY = 2
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class ReplicaState(enum.Enum):
|
|
75
|
+
# From rucio.db.sqla.constants, update that file at the same time as this
|
|
76
|
+
AVAILABLE = 'A'
|
|
77
|
+
UNAVAILABLE = 'U'
|
|
78
|
+
COPYING = 'C'
|
|
79
|
+
BEING_DELETED = 'B'
|
|
80
|
+
BAD = 'D'
|
|
81
|
+
TEMPORARY_UNAVAILABLE = 'T'
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@enum.unique
|
|
85
|
+
class HermesService(str, enum.Enum):
|
|
86
|
+
"""
|
|
87
|
+
The services supported by Hermes2.
|
|
88
|
+
"""
|
|
89
|
+
INFLUX = "INFLUX"
|
|
90
|
+
ELASTIC = "ELASTIC"
|
|
91
|
+
EMAIL = "EMAIL"
|
|
92
|
+
ACTIVEMQ = "ACTIVEMQ"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
# List of authorized value types for key
|
|
17
|
+
AUTHORIZED_VALUE_TYPES = (float, int, str)
|
|
18
|
+
STRING_TYPES = (str, )
|
rucio/common/didtype.py
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
DID type to represent a did and to simplify operations on it
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from rucio.common.exception import DIDError
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class DID(object):
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
Class used to store a DID
|
|
27
|
+
Given an object did of type DID
|
|
28
|
+
scope is stored in did.scope
|
|
29
|
+
name is stored in did.name
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
SCOPE_SEPARATOR = ':'
|
|
33
|
+
IMPLICIT_SCOPE_SEPARATOR = '.'
|
|
34
|
+
IMPLICIT_SCOPE_TO_LEN = {'user': 2, 'group': 2}
|
|
35
|
+
__slots__ = ['scope', 'name']
|
|
36
|
+
|
|
37
|
+
def __init__(self, *args, **kwargs):
|
|
38
|
+
"""
|
|
39
|
+
Constructs the DID object. Possible parameter combinations are:
|
|
40
|
+
DID()
|
|
41
|
+
DID('scope:name.did.str')
|
|
42
|
+
DID('user.implicit.scope.in.name')
|
|
43
|
+
DID('custom.scope', 'custom.name')
|
|
44
|
+
DID(['list.scope', 'list.name'])
|
|
45
|
+
DID(('tuple.scope', 'tuple.name'))
|
|
46
|
+
DID({'scope': 'dict.scope', 'name': 'dict.name'})
|
|
47
|
+
DID(scope='kw.scope')
|
|
48
|
+
DID(name='kw.name')
|
|
49
|
+
DID(name='user.kw.implicit.scope')
|
|
50
|
+
DID(scope='kw.scope', name='kw.name')
|
|
51
|
+
DID(did={'scope': 'kw.did.scope', 'name': 'kw.did.name'})
|
|
52
|
+
DID(did=['kw.list.scope', 'kw.list.name'])
|
|
53
|
+
DID(did=('kw.tuple.scope', 'kw.tuple.name'))
|
|
54
|
+
DID('arg.scope', name='kwarg.name')
|
|
55
|
+
DID('arg.name', scope='kwarg.scope')
|
|
56
|
+
"""
|
|
57
|
+
self.scope = self.name = ''
|
|
58
|
+
|
|
59
|
+
num_args = len(args)
|
|
60
|
+
num_kwargs = len(kwargs)
|
|
61
|
+
if (num_args + num_kwargs) > 2:
|
|
62
|
+
raise DIDError('Constructor takes at most 2 arguments. Given number: {}'.format(num_args + num_kwargs))
|
|
63
|
+
|
|
64
|
+
did = ''
|
|
65
|
+
if num_args == 1:
|
|
66
|
+
did = args[0]
|
|
67
|
+
|
|
68
|
+
if num_kwargs == 1:
|
|
69
|
+
if not isinstance(did, str):
|
|
70
|
+
raise DIDError('First argument of constructor is expected to be string type'
|
|
71
|
+
'when keyword argument is given. Given type: {}'.format(type(did)))
|
|
72
|
+
|
|
73
|
+
k, v = next(iter(kwargs.items()))
|
|
74
|
+
if k == 'scope':
|
|
75
|
+
did = (v, did)
|
|
76
|
+
elif k == 'name':
|
|
77
|
+
did = (did, v)
|
|
78
|
+
else:
|
|
79
|
+
raise DIDError('Constructor got unexpected keyword argument: {}'.format(k))
|
|
80
|
+
elif num_args == 0:
|
|
81
|
+
did = kwargs.get('did', kwargs)
|
|
82
|
+
else:
|
|
83
|
+
did = args
|
|
84
|
+
|
|
85
|
+
if isinstance(did, dict):
|
|
86
|
+
self.scope = did.get('scope', '')
|
|
87
|
+
self.name = did.get('name', '')
|
|
88
|
+
if not self.has_scope():
|
|
89
|
+
self.update_implicit_scope()
|
|
90
|
+
elif isinstance(did, tuple) or isinstance(did, list):
|
|
91
|
+
if len(did) != 2:
|
|
92
|
+
raise DIDError('Construction from tuple or list requires exactly 2 elements')
|
|
93
|
+
self.scope = did[0]
|
|
94
|
+
self.name = did[1]
|
|
95
|
+
elif isinstance(did, str):
|
|
96
|
+
did_parts = did.split(DID.SCOPE_SEPARATOR, 1)
|
|
97
|
+
if len(did_parts) == 1:
|
|
98
|
+
self.name = did
|
|
99
|
+
self.update_implicit_scope()
|
|
100
|
+
if not self.has_scope():
|
|
101
|
+
raise DIDError('Object construction from non-splitable string is ambigious')
|
|
102
|
+
else:
|
|
103
|
+
self.scope = did_parts[0]
|
|
104
|
+
self.name = did_parts[1]
|
|
105
|
+
elif isinstance(did, DID):
|
|
106
|
+
self.scope = did.scope
|
|
107
|
+
self.name = did.name
|
|
108
|
+
else:
|
|
109
|
+
raise DIDError('Cannot build object from: {}'.format(type(did)))
|
|
110
|
+
|
|
111
|
+
if self.name.endswith('/'):
|
|
112
|
+
self.name = self.name[:-1]
|
|
113
|
+
|
|
114
|
+
if not self.is_valid_format():
|
|
115
|
+
raise DIDError('Object has invalid format after construction: {}'.format(str(self)))
|
|
116
|
+
|
|
117
|
+
def update_implicit_scope(self):
|
|
118
|
+
"""
|
|
119
|
+
This method sets the scope if it is implicitly given in self.name
|
|
120
|
+
"""
|
|
121
|
+
did_parts = self.name.split(DID.IMPLICIT_SCOPE_SEPARATOR)
|
|
122
|
+
num_scope_parts = DID.IMPLICIT_SCOPE_TO_LEN.get(did_parts[0], 0)
|
|
123
|
+
if num_scope_parts > 0:
|
|
124
|
+
self.scope = '.'.join(did_parts[0:num_scope_parts])
|
|
125
|
+
|
|
126
|
+
def is_valid_format(self):
|
|
127
|
+
"""
|
|
128
|
+
Method to check if the stored DID has a valid format
|
|
129
|
+
:return: bool
|
|
130
|
+
"""
|
|
131
|
+
if self.scope.count(DID.SCOPE_SEPARATOR) or self.name.count(DID.SCOPE_SEPARATOR):
|
|
132
|
+
return False
|
|
133
|
+
return True
|
|
134
|
+
|
|
135
|
+
def has_scope(self):
|
|
136
|
+
"""
|
|
137
|
+
Method to check if the scope part was set
|
|
138
|
+
:return: bool
|
|
139
|
+
"""
|
|
140
|
+
return len(self.scope) > 0
|
|
141
|
+
|
|
142
|
+
def has_name(self):
|
|
143
|
+
"""
|
|
144
|
+
Method to check if the name part was set
|
|
145
|
+
:return: bool
|
|
146
|
+
"""
|
|
147
|
+
return len(self.name) > 0
|
|
148
|
+
|
|
149
|
+
def __str__(self):
|
|
150
|
+
"""
|
|
151
|
+
Creates the string representation of self
|
|
152
|
+
:return: string
|
|
153
|
+
"""
|
|
154
|
+
if self.has_scope() and self.has_name():
|
|
155
|
+
return '{}{}{}'.format(self.scope, DID.SCOPE_SEPARATOR, self.name)
|
|
156
|
+
elif self.has_scope():
|
|
157
|
+
return self.scope
|
|
158
|
+
return self.name
|
|
159
|
+
|
|
160
|
+
def __eq__(self, other):
|
|
161
|
+
"""
|
|
162
|
+
Equality comparison with another object
|
|
163
|
+
:return: bool
|
|
164
|
+
"""
|
|
165
|
+
if isinstance(other, str):
|
|
166
|
+
return str(self) == other
|
|
167
|
+
elif not isinstance(other, DID):
|
|
168
|
+
try:
|
|
169
|
+
other = DID(other)
|
|
170
|
+
except DIDError:
|
|
171
|
+
return False
|
|
172
|
+
|
|
173
|
+
return self.scope == other.scope and self.name == other.name
|
|
174
|
+
|
|
175
|
+
def __ne__(self, other):
|
|
176
|
+
"""
|
|
177
|
+
Inequality comparison with another object
|
|
178
|
+
:return: bool
|
|
179
|
+
"""
|
|
180
|
+
return not self.__eq__(other)
|
|
181
|
+
|
|
182
|
+
def __hash__(self):
|
|
183
|
+
"""
|
|
184
|
+
Uses the string representation of self to create a hash
|
|
185
|
+
:return: int
|
|
186
|
+
"""
|
|
187
|
+
return hash(str(self))
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
import bz2
|
|
17
|
+
import contextlib
|
|
18
|
+
import datetime
|
|
19
|
+
import gzip
|
|
20
|
+
import logging
|
|
21
|
+
import os
|
|
22
|
+
import re
|
|
23
|
+
import sys
|
|
24
|
+
import tempfile
|
|
25
|
+
|
|
26
|
+
import gfal2
|
|
27
|
+
import magic
|
|
28
|
+
import requests
|
|
29
|
+
|
|
30
|
+
from rucio.common import config
|
|
31
|
+
from rucio.core.rse import get_rse_id, get_rse_protocols
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class HTTPDownloadFailed(Exception):
|
|
35
|
+
def __init__(self, msg='', code=None):
|
|
36
|
+
self.code = code
|
|
37
|
+
if code is not None:
|
|
38
|
+
msg = '{0} (Status {1})'.format(msg, code)
|
|
39
|
+
super(HTTPDownloadFailed, self).__init__(msg)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class LogPipeHandler(logging.Handler, object):
|
|
43
|
+
def __init__(self, pipe):
|
|
44
|
+
super(LogPipeHandler, self).__init__()
|
|
45
|
+
self.pipe = pipe
|
|
46
|
+
|
|
47
|
+
def emit(self, record):
|
|
48
|
+
self.pipe.send(self.format(record))
|
|
49
|
+
|
|
50
|
+
def close(self):
|
|
51
|
+
super(LogPipeHandler, self).close()
|
|
52
|
+
self.pipe.close()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def error(text, exit_code=1):
|
|
56
|
+
'''
|
|
57
|
+
Log and print `text` error. This function ends the execution of the program with exit code
|
|
58
|
+
`exit_code` (defaults to 1).
|
|
59
|
+
'''
|
|
60
|
+
logger = logging.getLogger('dumper.__init__')
|
|
61
|
+
logger.error(text)
|
|
62
|
+
sys.stderr.write(text + '\n')
|
|
63
|
+
exit(1)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def mkdir(dir_):
|
|
67
|
+
'''
|
|
68
|
+
This functions creates the `dir_` directory if it doesn't exist. If `dir_`
|
|
69
|
+
already exists this function does nothing.
|
|
70
|
+
'''
|
|
71
|
+
try:
|
|
72
|
+
os.mkdir(dir_)
|
|
73
|
+
except OSError as error:
|
|
74
|
+
assert error.errno == 17
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def cacert_config(config, rucio_home):
|
|
78
|
+
logger = logging.getLogger('dumper.__init__')
|
|
79
|
+
try:
|
|
80
|
+
cacert = config.config_get('client', 'ca_cert').replace('$RUCIO_HOME', rucio_home)
|
|
81
|
+
except KeyError:
|
|
82
|
+
cacert = None
|
|
83
|
+
|
|
84
|
+
if cacert is None or not os.path.exists(cacert):
|
|
85
|
+
logger.warning('Configured CA Certificate file "%s" not found: Host certificate verification disabled', cacert)
|
|
86
|
+
cacert = False
|
|
87
|
+
|
|
88
|
+
return cacert
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def rucio_home():
|
|
92
|
+
return os.environ.get('RUCIO_HOME', '/opt/rucio')
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def get_requests_session():
|
|
96
|
+
requests_session = requests.Session()
|
|
97
|
+
requests_session.verify = cacert_config(config, rucio_home())
|
|
98
|
+
requests_session.stream = True
|
|
99
|
+
return requests_session
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
DUMPS_CACHE_DIR = 'cache'
|
|
103
|
+
RESULTS_DIR = 'results'
|
|
104
|
+
CHUNK_SIZE = 4194304 # 4MiB
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# There are two Python modules with the name `magic`, luckily both do
|
|
108
|
+
# the same thing.
|
|
109
|
+
# pylint: disable=no-member
|
|
110
|
+
if 'open' in dir(magic):
|
|
111
|
+
_mime = magic.open(magic.MAGIC_MIME)
|
|
112
|
+
_mime.load()
|
|
113
|
+
mimetype = _mime.file
|
|
114
|
+
else:
|
|
115
|
+
mimetype = lambda filename: magic.from_file(filename, mime=True) # NOQA
|
|
116
|
+
# pylint: enable=no-member
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def isplaintext(filename):
|
|
120
|
+
'''
|
|
121
|
+
Returns True if `filename` has mimetype == 'text/plain'.
|
|
122
|
+
'''
|
|
123
|
+
if os.path.islink(filename):
|
|
124
|
+
filename = os.readlink(filename)
|
|
125
|
+
return mimetype(filename).split(';')[0] == 'text/plain'
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def smart_open(filename):
|
|
129
|
+
'''
|
|
130
|
+
Returns an open file object if `filename` is plain text, else assumes
|
|
131
|
+
it is a bzip2 compressed file and returns a file-like object to
|
|
132
|
+
handle it.
|
|
133
|
+
'''
|
|
134
|
+
f = None
|
|
135
|
+
if isplaintext(filename):
|
|
136
|
+
f = open(filename, 'rt')
|
|
137
|
+
else:
|
|
138
|
+
file_type = mimetype(filename)
|
|
139
|
+
if file_type.find('gzip') > -1:
|
|
140
|
+
f = gzip.GzipFile(filename, 'rt')
|
|
141
|
+
elif file_type.find('bzip2') > -1:
|
|
142
|
+
f = bz2.open(filename, 'rt')
|
|
143
|
+
else:
|
|
144
|
+
pass # Not supported format
|
|
145
|
+
return f
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@contextlib.contextmanager
|
|
149
|
+
def temp_file(directory, final_name=None, binary=False):
|
|
150
|
+
'''
|
|
151
|
+
Allows to create a temporal file to store partial results, when the
|
|
152
|
+
file is complete it is renamed to `final_name`.
|
|
153
|
+
|
|
154
|
+
- `directory`: working path to create the temporal and the final file.
|
|
155
|
+
- `final_name`: Path of the final file, relative to `directory`.
|
|
156
|
+
If the `final_name` is omitted or None the renaming step is ommited,
|
|
157
|
+
leaving the temporal file with the results.
|
|
158
|
+
- `binary`: whether to open the file in binary mode (default: False).
|
|
159
|
+
|
|
160
|
+
Important: `directory` and `final_name` must be in the same filesystem as
|
|
161
|
+
a hardlink is used to rename the temporal file.
|
|
162
|
+
|
|
163
|
+
Example:
|
|
164
|
+
>>> with temp_file('/tmp', final_name='b') as (f, fname):
|
|
165
|
+
>>> print('The temporary file is named', fname)
|
|
166
|
+
>>> f.write('x')
|
|
167
|
+
>>> assert not os.path.exist('/tmp/' + fname)
|
|
168
|
+
>>> assert os.path.exist('/tmp/b')
|
|
169
|
+
'''
|
|
170
|
+
logger = logging.getLogger('dumper.__init__')
|
|
171
|
+
|
|
172
|
+
fd, tpath = tempfile.mkstemp(dir=directory)
|
|
173
|
+
tmp = os.fdopen(fd, 'wb' if binary else 'w')
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
yield tmp, os.path.basename(tpath)
|
|
177
|
+
except:
|
|
178
|
+
# Close and remove temporal file on failure
|
|
179
|
+
tmp.close()
|
|
180
|
+
os.unlink(tpath)
|
|
181
|
+
raise
|
|
182
|
+
|
|
183
|
+
tmp.close()
|
|
184
|
+
if final_name is not None:
|
|
185
|
+
dst_path = os.path.join(directory, final_name)
|
|
186
|
+
logger.debug('Renaming "%s" to "%s"', tpath, dst_path)
|
|
187
|
+
os.link(tpath, dst_path)
|
|
188
|
+
os.unlink(tpath)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
|
|
192
|
+
DATETIME_FORMAT_FULL = '%Y-%m-%dT%H:%M:%S'
|
|
193
|
+
MILLISECONDS_RE = re.compile(r'\.(\d{3})Z$')
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def to_datetime(str_or_datetime):
|
|
197
|
+
"""
|
|
198
|
+
Convert string to datetime. The format is somewhat flexible.
|
|
199
|
+
Timezone information is ignored.
|
|
200
|
+
"""
|
|
201
|
+
logger = logging.getLogger('dumper.__init__')
|
|
202
|
+
if isinstance(str_or_datetime, datetime.datetime):
|
|
203
|
+
return str_or_datetime
|
|
204
|
+
elif str_or_datetime.strip() == '':
|
|
205
|
+
return None
|
|
206
|
+
|
|
207
|
+
str_or_datetime = str_or_datetime.replace('T', ' ')
|
|
208
|
+
try:
|
|
209
|
+
logger.debug(
|
|
210
|
+
'Trying to parse "%s" date with '
|
|
211
|
+
'resolution of seconds or tenths of seconds',
|
|
212
|
+
str_or_datetime,
|
|
213
|
+
)
|
|
214
|
+
str_or_datetime = re.sub(r'\.\d$', '', str_or_datetime)
|
|
215
|
+
date = datetime.datetime.strptime(
|
|
216
|
+
str_or_datetime,
|
|
217
|
+
DATETIME_FORMAT,
|
|
218
|
+
)
|
|
219
|
+
except ValueError:
|
|
220
|
+
logger.debug(
|
|
221
|
+
'Trying to parse "%s" date with resolution of milliseconds',
|
|
222
|
+
str_or_datetime,
|
|
223
|
+
)
|
|
224
|
+
miliseconds = int(MILLISECONDS_RE.search(str_or_datetime).group(1))
|
|
225
|
+
str_or_datetime = MILLISECONDS_RE.sub('', str_or_datetime)
|
|
226
|
+
date = datetime.datetime.strptime(
|
|
227
|
+
str_or_datetime,
|
|
228
|
+
DATETIME_FORMAT,
|
|
229
|
+
)
|
|
230
|
+
date = date + datetime.timedelta(microseconds=miliseconds * 1000)
|
|
231
|
+
return date
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def ddmendpoint_preferred_protocol(ddmendpoint):
|
|
235
|
+
return next(p for p in get_rse_protocols(get_rse_id(ddmendpoint))['protocols'] if p['domains']['wan']['read'] == 1)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def ddmendpoint_url(ddmendpoint):
|
|
239
|
+
preferred_protocol = ddmendpoint_preferred_protocol(ddmendpoint)
|
|
240
|
+
prefix = re.sub(r'rucio/$', '', preferred_protocol['prefix'])
|
|
241
|
+
return '{scheme}://{hostname}:{port}'.format(**preferred_protocol) + prefix
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def http_download_to_file(url, file_, session=None):
|
|
245
|
+
'''
|
|
246
|
+
Download the file in `url` storing it in the `file_` file-like
|
|
247
|
+
object.
|
|
248
|
+
If given `session` must be a requests.Session instance, and will be
|
|
249
|
+
used to download the file, otherwise requests.get() will be used.
|
|
250
|
+
'''
|
|
251
|
+
if session is None:
|
|
252
|
+
response = requests.get(url, stream=True)
|
|
253
|
+
else:
|
|
254
|
+
response = session.get(url)
|
|
255
|
+
|
|
256
|
+
if response.status_code != 200:
|
|
257
|
+
logging.error(
|
|
258
|
+
'Retrieving %s returned %d status code',
|
|
259
|
+
url,
|
|
260
|
+
response.status_code,
|
|
261
|
+
)
|
|
262
|
+
raise HTTPDownloadFailed('Error downloading ' + url, response.status_code)
|
|
263
|
+
|
|
264
|
+
for chunk in response.iter_content(CHUNK_SIZE):
|
|
265
|
+
file_.write(chunk)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def http_download(url, filename):
|
|
269
|
+
'''
|
|
270
|
+
Download the file in `url` storing it in the path given by `filename`.
|
|
271
|
+
'''
|
|
272
|
+
with open(filename, 'w') as f:
|
|
273
|
+
http_download_to_file(url, f)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def gfal_download_to_file(url, file_):
|
|
277
|
+
'''
|
|
278
|
+
Download the file in `url` storing it in the `file_` file-like
|
|
279
|
+
object.
|
|
280
|
+
'''
|
|
281
|
+
logger = logging.getLogger('dumper.__init__')
|
|
282
|
+
ctx = gfal2.creat_context() # pylint: disable=no-member
|
|
283
|
+
infile = ctx.open(url, 'r')
|
|
284
|
+
|
|
285
|
+
try:
|
|
286
|
+
chunk = infile.read(CHUNK_SIZE)
|
|
287
|
+
except gfal2.GError as e:
|
|
288
|
+
if e.code == 70:
|
|
289
|
+
logger.debug('GError(70) raised, using GRIDFTP PLUGIN:STAT_ON_OPEN=False workarround to download %s', url)
|
|
290
|
+
ctx.set_opt_boolean('GRIDFTP PLUGIN', 'STAT_ON_OPEN', False)
|
|
291
|
+
infile = ctx.open(url, 'r')
|
|
292
|
+
chunk = infile.read(CHUNK_SIZE)
|
|
293
|
+
else:
|
|
294
|
+
raise
|
|
295
|
+
|
|
296
|
+
while chunk:
|
|
297
|
+
file_.write(chunk)
|
|
298
|
+
chunk = infile.read(CHUNK_SIZE)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def gfal_download(url, filename):
|
|
302
|
+
'''
|
|
303
|
+
Download the file in `url` storing it in the path given by `filename`.
|
|
304
|
+
'''
|
|
305
|
+
with open(filename, 'w') as f:
|
|
306
|
+
gfal_download_to_file(url, f)
|