rucio-clients 38.4.0__tar.gz → 38.5.0__tar.gz
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-clients might be problematic. Click here for more details.
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/PKG-INFO +1 -1
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/etc/rucio.cfg.template +2 -3
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/bin_legacy/rucio.py +12 -7
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/bin_legacy/rucio_admin.py +9 -2
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/replica.py +6 -2
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/rule.py +0 -1
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/scope.py +9 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/utils.py +11 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/downloadclient.py +3 -1
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/scopeclient.py +40 -1
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/didtype.py +18 -11
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/vcsversion.py +3 -3
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_bin_rucio.py +79 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_cli_client_structure.py +13 -4
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_conveyor.py +22 -15
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_did_meta_plugins.py +21 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_gateway_external_representation.py +1 -1
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_multi_vo.py +2 -2
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_policy_package.py +41 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse.py +14 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_scope.py +64 -2
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/AUTHORS.rst +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/ChangeLog +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/LICENSE +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/MANIFEST.in +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/README.md +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/bin/rucio +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/bin/rucio-admin +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/etc/rse-accounts.cfg.template +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/__init__.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/alembicrevision.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/__init__.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/account.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/bin_legacy/__init__.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/command.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/config.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/did.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/download.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/lifetime_exception.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/opendata.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/rse.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/subscription.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/cli/upload.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/__init__.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/accountclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/accountlimitclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/baseclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/client.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/configclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/credentialclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/didclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/diracclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/exportclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/importclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/lifetimeclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/lockclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/metaconventionsclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/opendataclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/pingclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/replicaclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/requestclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/richclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/rseclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/ruleclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/subscriptionclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/touchclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/client/uploadclient.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/__init__.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/bittorrent.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/cache.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/checksum.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/client.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/config.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/constants.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/constraints.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/exception.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/extra.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/logging.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/pcache.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/plugins.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/policy.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/schema/__init__.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/schema/generic.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/schema/generic_multi_vo.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/stomp_utils.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/stopwatch.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/test_rucio_server.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/types.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/common/utils.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/__init__.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/__init__.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/bittorrent.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/cache.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/dummy.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/gfal.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/globus.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/http_cache.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/mock.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/ngarc.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/posix.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/protocol.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/rclone.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/rfio.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/srm.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/ssh.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/storm.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/webdav.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/protocols/xrootd.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/rsemanager.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/rse/translation.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio/version.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/lib/rucio_clients.egg-info/SOURCES.txt +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/pyproject.toml +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/requirements/requirements.client.txt +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/setup.cfg +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/setup.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/setuputil.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_abacus_account.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_abacus_collection_replica.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_abacus_rse.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_account.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_account_limits.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_archive.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_auditor.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_auditor_hdfs.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_auditor_srmdumps.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_authentication.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_automatix.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_bad_replica.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_bb8.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_belleii.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_boolean.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_clients.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_config.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_conveyor_submitter.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_counter.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_credential.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_curl.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_daemons.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_dataset_replicas.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_db.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_did.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_download.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_dumper.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_filter_engine.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_heartbeat.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_hermes.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_identity.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_impl_upload_download.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_import_export.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_judge_cleaner.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_judge_evaluator.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_judge_injector.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_judge_repairer.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_lifetime.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_message.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_meta_conventions.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_meta_did.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_module_import.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_monitor.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_naming_convention.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_oauthmanager.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_oidc.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_opendata.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_permission.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_pfns.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_ping.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_preparer.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_qos.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_quarantined_replica.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_reaper.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_redirect.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_replica.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_replica_recoverer.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_replica_sorting.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_request.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_root_proxy.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_expression_parser.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_lfn2path.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_protocol_gfal2.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_protocol_gfal2_impl.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_protocol_posix.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_protocol_rclone.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_protocol_rsync.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_protocol_srm.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_protocol_ssh.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_protocol_webdav.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_protocol_xrootd.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rse_selector.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rucio_server.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_rule.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_subscription.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_throttler.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_tpc.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_trace.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_transfer.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_transfer_plugins.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_undertaker.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_upload.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tests/test_utils.py +0 -0
- {rucio_clients-38.4.0 → rucio_clients-38.5.0}/tools/merge_rucio_configs.py +0 -0
|
@@ -121,8 +121,8 @@ usercert = /opt/rucio/tools/x509up
|
|
|
121
121
|
|
|
122
122
|
[messaging-fts3]
|
|
123
123
|
port = 61123
|
|
124
|
-
ssl_key_file = /
|
|
125
|
-
ssl_cert_file = /
|
|
124
|
+
ssl_key_file = /etc/grid-security/hostkey.pem
|
|
125
|
+
ssl_cert_file = /etc/grid-security/hostcert.pem
|
|
126
126
|
destination = /topic/transfer.fts_monitoring_queue_state
|
|
127
127
|
brokers = dashb-test-mb.cern.ch
|
|
128
128
|
voname = atlas
|
|
@@ -199,7 +199,6 @@ account = cache_mb
|
|
|
199
199
|
cacert = /opt/rucio/etc/web/ca.crt
|
|
200
200
|
#cacert = /etc/pki/tls/certs/CERN-bundle.pem
|
|
201
201
|
usercert = /opt/rucio/etc/web/usercert.pem
|
|
202
|
-
#usercert = /home/mario/.ssh/usercert_with_key.pem
|
|
203
202
|
|
|
204
203
|
[nagios]
|
|
205
204
|
proxy = /opt/rucio/etc/ddmadmin.proxy.nagios
|
|
@@ -36,7 +36,7 @@ from tabulate import tabulate
|
|
|
36
36
|
|
|
37
37
|
# rucio module has the same name as this executable module, so this rule fails. pylint: disable=no-name-in-module
|
|
38
38
|
from rucio import version
|
|
39
|
-
from rucio.cli.utils import exception_handler, get_client, setup_gfal2_logger, signal_handler
|
|
39
|
+
from rucio.cli.utils import exception_handler, get_client, scope_exists, setup_gfal2_logger, signal_handler
|
|
40
40
|
from rucio.client.richclient import MAX_TRACEBACK_WIDTH, MIN_CONSOLE_WIDTH, CLITheme, generate_table, get_cli_config, get_pager, print_output, setup_rich_logger
|
|
41
41
|
from rucio.common.client import detect_client_location
|
|
42
42
|
from rucio.common.config import config_get, config_get_float
|
|
@@ -48,7 +48,6 @@ from rucio.common.exception import (
|
|
|
48
48
|
InvalidType,
|
|
49
49
|
RSENotFound,
|
|
50
50
|
RucioException,
|
|
51
|
-
ScopeNotFound,
|
|
52
51
|
UnsupportedOperation,
|
|
53
52
|
)
|
|
54
53
|
from rucio.common.extra import import_extras
|
|
@@ -459,8 +458,7 @@ def list_dids(args, client, logger, console, spinner):
|
|
|
459
458
|
scope = args.did[0]
|
|
460
459
|
name = '*'
|
|
461
460
|
|
|
462
|
-
|
|
463
|
-
raise ScopeNotFound
|
|
461
|
+
scope_exists(client, scope)
|
|
464
462
|
|
|
465
463
|
if args.recursive and '*' in name:
|
|
466
464
|
raise InputValidationError('Option recursive cannot be used with wildcards.')
|
|
@@ -522,12 +520,19 @@ def list_scopes(args, client, logger, console, spinner):
|
|
|
522
520
|
scopes = client.list_scopes()
|
|
523
521
|
if (cli_config == 'rich') and (not args.csv):
|
|
524
522
|
scopes = [[scope] for scope in sorted(scopes)]
|
|
525
|
-
table = generate_table(scopes, headers=['SCOPE'], col_alignments=['left'])
|
|
523
|
+
table = generate_table(scopes, headers=['SCOPE', 'ACCOUNT'], col_alignments=['left'])
|
|
526
524
|
spinner.stop()
|
|
527
525
|
print_output(table, console=console, no_pager=args.no_pager)
|
|
528
526
|
else:
|
|
529
|
-
|
|
530
|
-
|
|
527
|
+
if isinstance(scopes[0], str): # TODO: Backwards compatibility - remove in v40 issue #8125
|
|
528
|
+
for scope in scopes:
|
|
529
|
+
print(scope)
|
|
530
|
+
elif args.csv:
|
|
531
|
+
for scope in scopes:
|
|
532
|
+
print(scope['scope'])
|
|
533
|
+
else:
|
|
534
|
+
scopes = [[s['scope'], s['account']] for s in scopes]
|
|
535
|
+
print(tabulate(scopes, tablefmt=tablefmt, headers=['SCOPE', 'ACCOUNT'], disable_numparse=True))
|
|
531
536
|
return SUCCESS
|
|
532
537
|
|
|
533
538
|
|
|
@@ -780,8 +780,15 @@ def list_scopes(args, client, logger, console, spinner):
|
|
|
780
780
|
spinner.stop()
|
|
781
781
|
print_output(table, console=console, no_pager=args.no_pager)
|
|
782
782
|
else:
|
|
783
|
-
|
|
784
|
-
|
|
783
|
+
if isinstance(scopes[0], str): # TODO: Backwards compatibility - remove in v40 issue #8125
|
|
784
|
+
for scope in scopes:
|
|
785
|
+
print(scope)
|
|
786
|
+
elif args.csv:
|
|
787
|
+
for scope in scopes:
|
|
788
|
+
print(scope['scope'])
|
|
789
|
+
else:
|
|
790
|
+
scopes = [[s['scope'], s['account']] for s in scopes]
|
|
791
|
+
print(tabulate(scopes, tablefmt=tablefmt, headers=['SCOPE', 'ACCOUNT'], disable_numparse=True))
|
|
785
792
|
return SUCCESS
|
|
786
793
|
|
|
787
794
|
|
|
@@ -129,11 +129,15 @@ def update_bad(ctx, replicas, reason, as_file, collection, lfn, scope, rse):
|
|
|
129
129
|
"""Mark a replica bad"""
|
|
130
130
|
args = {"reason": reason, "allow_collection": collection, "scope": scope, "rse": rse}
|
|
131
131
|
if as_file:
|
|
132
|
-
|
|
132
|
+
if len(replicas) != 1:
|
|
133
|
+
raise ValueError("Exactly one positional argument expected in case as-file")
|
|
134
|
+
args["inputfile"] = replicas[0]
|
|
133
135
|
elif lfn:
|
|
134
136
|
if (scope is None) or (rse is None):
|
|
135
137
|
raise ValueError("Scope and RSE are required when using LFNs")
|
|
136
|
-
|
|
138
|
+
if len(replicas) != 1:
|
|
139
|
+
raise ValueError("Exactly one positional argument expected in case of LFN list")
|
|
140
|
+
args["lfns"] = replicas[0]
|
|
137
141
|
else:
|
|
138
142
|
args["listbadfiles"] = replicas
|
|
139
143
|
declare_bad_file_replicas(Arguments(args), ctx.obj.client, ctx.obj.logger, ctx.obj.console, ctx.obj.spinner)
|
|
@@ -118,7 +118,6 @@ def move(ctx, rule_id, rses, activity, source_rses):
|
|
|
118
118
|
@click.option("--account", help="The account owning the rule")
|
|
119
119
|
@click.option("--stuck", is_flag=True, default=False, help="Set state to STUCK.")
|
|
120
120
|
@click.option('--suspend', is_flag=True, default=None, help='Set state to SUSPENDED.')
|
|
121
|
-
@click.option("--activity", help="Activity of the rule.")
|
|
122
121
|
@click.option("--cancel-requests", is_flag=True, default=False, help="Cancel requests when setting rules to stuck.")
|
|
123
122
|
@click.option("--priority", help="Priority of the requests of the rule.")
|
|
124
123
|
@click.option("--child-rule-id", help='Child rule id of the rule. Use "None" to remove an existing parent/child relationship.')
|
|
@@ -39,3 +39,12 @@ def add_(ctx, account, scope_name):
|
|
|
39
39
|
def list_(ctx: click.Context, account: str, csv: bool):
|
|
40
40
|
"""List existing scopes"""
|
|
41
41
|
list_scopes(Arguments({"no_pager": ctx.obj.no_pager, "account": account, "csv": csv}), ctx.obj.client, ctx.obj.logger, ctx.obj.console, ctx.obj.spinner)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@scope.command("update")
|
|
45
|
+
@click.argument('scope-name')
|
|
46
|
+
@click.option('-a', '--account', help="New account to associate with the scope", required=True)
|
|
47
|
+
@click.pass_context
|
|
48
|
+
def update(ctx: click.Context, scope_name: str, account: str):
|
|
49
|
+
"""Update the ownership of a [SCOPE-NAME]"""
|
|
50
|
+
ctx.obj.client.update_scope_ownership(account=account, scope=scope_name)
|
|
@@ -41,6 +41,7 @@ from rucio.common.exception import (
|
|
|
41
41
|
RSENotFound,
|
|
42
42
|
RucioException,
|
|
43
43
|
RuleNotFound,
|
|
44
|
+
ScopeNotFound,
|
|
44
45
|
UnsupportedOperation,
|
|
45
46
|
)
|
|
46
47
|
from rucio.common.utils import setup_logger
|
|
@@ -260,3 +261,13 @@ class JSONType(click.ParamType):
|
|
|
260
261
|
return json.loads(value)
|
|
261
262
|
except json.JSONDecodeError as e:
|
|
262
263
|
self.fail(f"Invalid JSON: {e}", param, ctx)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def scope_exists(client: 'Client', scope: str) -> None:
|
|
267
|
+
possible_scopes = client.list_scopes()
|
|
268
|
+
if isinstance(possible_scopes[0], str): # type: ignore #TODO Backwards Compat - Remove in v40, #8125
|
|
269
|
+
scopes = possible_scopes
|
|
270
|
+
else:
|
|
271
|
+
scopes = [s['scope'] for s in possible_scopes] # type: ignore
|
|
272
|
+
if scope not in scopes: # type: ignore - handled by the if isinstance
|
|
273
|
+
raise ScopeNotFound
|
|
@@ -1856,7 +1856,9 @@ class DownloadClient:
|
|
|
1856
1856
|
did_name = did[1]
|
|
1857
1857
|
elif len(did) == 1:
|
|
1858
1858
|
if self.extract_scope_convention == 'belleii':
|
|
1859
|
-
scopes =
|
|
1859
|
+
scopes = self.client.list_scopes()
|
|
1860
|
+
if not isinstance(scopes, list):
|
|
1861
|
+
scopes = [scope['scope'] for scope in scopes]
|
|
1860
1862
|
did_scope, did_name = extract_scope(did[0], scopes)
|
|
1861
1863
|
else:
|
|
1862
1864
|
did = did_str.split('.')
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from json import loads
|
|
16
|
+
from typing import TYPE_CHECKING, Any, Literal, Union
|
|
16
17
|
from urllib.parse import quote_plus
|
|
17
18
|
|
|
18
19
|
from requests.status_codes import codes
|
|
@@ -21,6 +22,9 @@ from rucio.client.baseclient import BaseClient, choice
|
|
|
21
22
|
from rucio.common.constants import HTTPMethod
|
|
22
23
|
from rucio.common.utils import build_url
|
|
23
24
|
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from collections.abc import Iterator
|
|
27
|
+
|
|
24
28
|
|
|
25
29
|
class ScopeClient(BaseClient):
|
|
26
30
|
|
|
@@ -64,7 +68,7 @@ class ScopeClient(BaseClient):
|
|
|
64
68
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
65
69
|
raise exc_cls(exc_msg)
|
|
66
70
|
|
|
67
|
-
def list_scopes(self) -> list[str]:
|
|
71
|
+
def list_scopes(self) -> "Union[list[str], Iterator[dict[Literal['scope', 'account'], Any]]]":
|
|
68
72
|
"""
|
|
69
73
|
Sends the request to list all scopes.
|
|
70
74
|
|
|
@@ -83,6 +87,41 @@ class ScopeClient(BaseClient):
|
|
|
83
87
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
84
88
|
raise exc_cls(exc_msg)
|
|
85
89
|
|
|
90
|
+
def update_scope_ownership(self, account: str, scope: str) -> bool:
|
|
91
|
+
"""
|
|
92
|
+
Change the ownership of a scope
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
account :
|
|
97
|
+
New account to assign as scope owner
|
|
98
|
+
scope :
|
|
99
|
+
Scope to change ownership of
|
|
100
|
+
|
|
101
|
+
Returns
|
|
102
|
+
-------
|
|
103
|
+
bool
|
|
104
|
+
True if the operation was successful
|
|
105
|
+
|
|
106
|
+
Raises
|
|
107
|
+
------
|
|
108
|
+
AccountNotFound
|
|
109
|
+
If account doesn't exist.
|
|
110
|
+
ScopeNotFound
|
|
111
|
+
If scope doesn't exist.
|
|
112
|
+
CannotAuthenticate, AccessDenied
|
|
113
|
+
Insufficient permission/incorrect credentials to change ownership.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
path = '/'.join(['scopes', account, scope])
|
|
117
|
+
url = build_url(choice(self.list_hosts), path=path)
|
|
118
|
+
r = self._send_request(url, method=HTTPMethod.PUT)
|
|
119
|
+
if r.status_code == codes.ok:
|
|
120
|
+
return True
|
|
121
|
+
else:
|
|
122
|
+
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
123
|
+
raise exc_cls(exc_msg)
|
|
124
|
+
|
|
86
125
|
def list_scopes_for_account(self, account: str) -> list[str]:
|
|
87
126
|
"""
|
|
88
127
|
Sends the request to list all scopes for a rucio account.
|
|
@@ -15,10 +15,12 @@
|
|
|
15
15
|
"""
|
|
16
16
|
DID type to represent a DID and to simplify operations on it
|
|
17
17
|
"""
|
|
18
|
-
|
|
18
|
+
import logging
|
|
19
|
+
from configparser import NoSectionError
|
|
19
20
|
from typing import Any, Union
|
|
20
21
|
|
|
21
|
-
from rucio.common.exception import DIDError
|
|
22
|
+
from rucio.common.exception import ConfigNotFound, DIDError, InvalidAlgorithmName
|
|
23
|
+
from rucio.common.utils import extract_scope
|
|
22
24
|
|
|
23
25
|
|
|
24
26
|
class DID:
|
|
@@ -126,15 +128,20 @@ class DID:
|
|
|
126
128
|
Construct the DID from a string.
|
|
127
129
|
:param did: string containing the DID information
|
|
128
130
|
"""
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
try:
|
|
132
|
+
self.scope, self.name = extract_scope(did)
|
|
133
|
+
except (ImportError, InvalidAlgorithmName, ConfigNotFound, NoSectionError) as e: # Only use when the policy can not be found
|
|
134
|
+
logging.debug("Failure using extract_scope policy for '%s': %s - Using fallback." % (did, type(e).__name__))
|
|
135
|
+
did_parts = did.split(DID.SCOPE_SEPARATOR, 1)
|
|
136
|
+
if len(did_parts) == 1:
|
|
137
|
+
self.name = did
|
|
138
|
+
self._update_implicit_scope()
|
|
139
|
+
if not self.has_scope():
|
|
140
|
+
error = f"Could not parse scope from did string {did} - fallback policy expects only one '{DID.SCOPE_SEPARATOR}'"
|
|
141
|
+
raise DIDError(error)
|
|
142
|
+
else:
|
|
143
|
+
self.scope = did_parts[0]
|
|
144
|
+
self.name = did_parts[1]
|
|
138
145
|
|
|
139
146
|
def _did_from_dict(self, did: dict[str, str]) -> None:
|
|
140
147
|
"""
|
|
@@ -4,8 +4,8 @@ This file is automatically generated; Do not edit it. :)
|
|
|
4
4
|
'''
|
|
5
5
|
VERSION_INFO = {
|
|
6
6
|
'final': True,
|
|
7
|
-
'version': '38.
|
|
7
|
+
'version': '38.5.0',
|
|
8
8
|
'branch_nick': 'release-38-LTS',
|
|
9
|
-
'revision_id': '
|
|
10
|
-
'revno':
|
|
9
|
+
'revision_id': '430fd3dd8f4dc5103e1e932c9515421e1c515c3e',
|
|
10
|
+
'revno': 14073
|
|
11
11
|
}
|
|
@@ -12,9 +12,11 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import logging
|
|
15
16
|
import os
|
|
16
17
|
import random
|
|
17
18
|
import re
|
|
19
|
+
import shlex
|
|
18
20
|
import tempfile
|
|
19
21
|
from datetime import datetime, timedelta, timezone
|
|
20
22
|
|
|
@@ -1292,3 +1294,80 @@ def test_download_file_check_by_size(rse_factory, mock_scope, did_factory):
|
|
|
1292
1294
|
exitcode, out, err = execute(cmd)
|
|
1293
1295
|
assert exitcode == 0
|
|
1294
1296
|
assert "File with same name exists locally, but filesize mismatches" in err
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
@pytest.mark.parametrize(
|
|
1300
|
+
("cli", "lfn"),
|
|
1301
|
+
[
|
|
1302
|
+
("new", True),
|
|
1303
|
+
("old", True),
|
|
1304
|
+
("new", False),
|
|
1305
|
+
("old", False),
|
|
1306
|
+
]
|
|
1307
|
+
)
|
|
1308
|
+
def test_cli_declare_bad_replicas(cli, lfn, rse_factory, mock_scope, did_factory, tmp_path, rucio_client):
|
|
1309
|
+
"""CLIENT(USER): Rucio declare bad replica"""
|
|
1310
|
+
log = logging.getLogger("bad-replicas")
|
|
1311
|
+
|
|
1312
|
+
rse, _ = rse_factory.make_posix_rse()
|
|
1313
|
+
scope = mock_scope.external
|
|
1314
|
+
|
|
1315
|
+
did = did_factory.upload_test_file(rse_name=rse, scope=scope)
|
|
1316
|
+
# replace scope object with scope name str
|
|
1317
|
+
did["scope"] = did["scope"].external
|
|
1318
|
+
|
|
1319
|
+
cmd = []
|
|
1320
|
+
if cli == "new":
|
|
1321
|
+
cmd = ["rucio", "replica", "state", "update", "bad"]
|
|
1322
|
+
else:
|
|
1323
|
+
cmd = ["rucio-admin", "replicas", "declare-bad"]
|
|
1324
|
+
|
|
1325
|
+
cmd.extend(["--reason", "test"])
|
|
1326
|
+
|
|
1327
|
+
bad_replicas = []
|
|
1328
|
+
|
|
1329
|
+
if lfn:
|
|
1330
|
+
lfn_path = tmp_path / "lfns.txt"
|
|
1331
|
+
lfn_path.write_text(did["name"] + "\n")
|
|
1332
|
+
|
|
1333
|
+
if cli == "new":
|
|
1334
|
+
cmd.append("--lfn")
|
|
1335
|
+
bad_replicas.append(str(lfn_path))
|
|
1336
|
+
else:
|
|
1337
|
+
cmd.extend(["--lfns", str(lfn_path)])
|
|
1338
|
+
|
|
1339
|
+
cmd.extend(["--rse", rse, "--scope", scope])
|
|
1340
|
+
else:
|
|
1341
|
+
bad_replicas.append(f"{did['scope']}:{did['name']}")
|
|
1342
|
+
|
|
1343
|
+
cmd.extend(bad_replicas)
|
|
1344
|
+
cmd = shlex.join(cmd)
|
|
1345
|
+
|
|
1346
|
+
code, stdout, stderr = execute(cmd)
|
|
1347
|
+
log.info("Command stdout:\n%s", stdout)
|
|
1348
|
+
log.warning("Command stderr:\n%s", stderr)
|
|
1349
|
+
assert code == 0, f"Running {cmd} failed. out:\n{stdout}\nerr\n{stderr}"
|
|
1350
|
+
|
|
1351
|
+
replicas = next(rucio_client.list_replicas([did], rse_expression=rse, all_states=True))
|
|
1352
|
+
assert replicas["states"][rse] == "BAD"
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
def test_cli_declare_bad_replicas_invalid_usage():
|
|
1356
|
+
"""CLIENT(USER): Rucio declare bad replica invalid argument handling"""
|
|
1357
|
+
base_cmd = ["rucio", "replica", "state", "update", "bad"]
|
|
1358
|
+
|
|
1359
|
+
def run(expected_error, args=None, expected_code=1):
|
|
1360
|
+
args = args or []
|
|
1361
|
+
cmd = shlex.join(base_cmd + args)
|
|
1362
|
+
code, stdout, stderr = execute(cmd)
|
|
1363
|
+
|
|
1364
|
+
assert code == expected_code, f"Running {cmd} did not fail as expected. out:\n{stdout}\nerr\n{stderr}"
|
|
1365
|
+
assert expected_error in stderr, f"Expected error message not found in stderr:\n{stderr}"
|
|
1366
|
+
|
|
1367
|
+
run("Missing option '--reason'", expected_code=2)
|
|
1368
|
+
|
|
1369
|
+
args = ["--reason", "test", "--lfn", "foo"]
|
|
1370
|
+
run("Scope and RSE are required", args=args, expected_code=1)
|
|
1371
|
+
|
|
1372
|
+
args = ["--reason", "test", "--scope", "test", "--rse", "test", "--lfn", "foo", "bar"]
|
|
1373
|
+
run("Exactly one", args=args, expected_code=1)
|
|
@@ -857,20 +857,29 @@ def test_rule(rucio_client, mock_scope):
|
|
|
857
857
|
assert len(out.split("\n")) == 3 # Creates two rules with independent IDs and one extra line at the end
|
|
858
858
|
|
|
859
859
|
|
|
860
|
-
def test_scope():
|
|
861
|
-
|
|
862
|
-
|
|
860
|
+
def test_scope(rucio_client, scope_factory, random_account_factory, vo):
|
|
861
|
+
scope = scope_name_generator()
|
|
862
|
+
account = random_account_factory().external
|
|
863
|
+
cmd = f"rucio scope add {scope} --account {account}"
|
|
863
864
|
exitcode, _, err = execute(cmd)
|
|
864
865
|
assert exitcode == 0
|
|
865
866
|
assert "ERROR" not in err
|
|
866
867
|
|
|
867
|
-
cmd = "rucio scope list --account
|
|
868
|
+
cmd = f"rucio scope list --account {account}"
|
|
868
869
|
exitcode, out, err = execute(cmd)
|
|
869
870
|
assert exitcode == 0
|
|
870
871
|
assert "ERROR" not in err
|
|
871
872
|
# assert new_scope in out
|
|
872
873
|
# See issue https://github.com/rucio/rucio/issues/7316
|
|
873
874
|
|
|
875
|
+
new_scope, _ = scope_factory(vos=[vo], account_name=account)
|
|
876
|
+
new_account = random_account_factory().external
|
|
877
|
+
cmd = f"rucio scope update {new_scope} --account {new_account}"
|
|
878
|
+
exitcode, out, err = execute(cmd)
|
|
879
|
+
assert exitcode == 0
|
|
880
|
+
assert "ERROR" not in err
|
|
881
|
+
assert new_scope in rucio_client.list_scopes_for_account(new_account)
|
|
882
|
+
|
|
874
883
|
|
|
875
884
|
def test_subscription(rucio_client, mock_scope):
|
|
876
885
|
subscription_name = generate_uuid()
|
|
@@ -452,7 +452,6 @@ def test_multisource(vo, did_factory, root_account, replica_client, caches_mock,
|
|
|
452
452
|
)
|
|
453
453
|
|
|
454
454
|
|
|
455
|
-
@pytest.mark.skip(reason="Pending https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC4506150")
|
|
456
455
|
@skip_rse_tests_with_accounts
|
|
457
456
|
@pytest.mark.dirty(reason="leaves files in XRD containers")
|
|
458
457
|
@pytest.mark.noparallel(groups=[NoParallelGroups.XRD, NoParallelGroups.SUBMITTER, NoParallelGroups.RECEIVER])
|
|
@@ -526,7 +525,6 @@ def test_multisource_receiver(vo, did_factory, replica_client, root_account, met
|
|
|
526
525
|
RECEIVER_GRACEFUL_STOP.clear()
|
|
527
526
|
|
|
528
527
|
|
|
529
|
-
@pytest.mark.skip(reason="Pending https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC4506150")
|
|
530
528
|
@skip_rse_tests_with_accounts
|
|
531
529
|
@pytest.mark.noparallel(groups=[NoParallelGroups.XRD, NoParallelGroups.SUBMITTER, NoParallelGroups.RECEIVER])
|
|
532
530
|
@pytest.mark.parametrize("caches_mock", [{"caches_to_mock": [
|
|
@@ -581,7 +579,6 @@ def test_multihop_receiver_on_failure(vo, did_factory, replica_client, root_acco
|
|
|
581
579
|
RECEIVER_GRACEFUL_STOP.clear()
|
|
582
580
|
|
|
583
581
|
|
|
584
|
-
@pytest.mark.skip(reason="Pending https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC4506150")
|
|
585
582
|
@skip_rse_tests_with_accounts
|
|
586
583
|
@pytest.mark.noparallel(groups=[NoParallelGroups.XRD, NoParallelGroups.SUBMITTER, NoParallelGroups.RECEIVER])
|
|
587
584
|
@pytest.mark.parametrize("caches_mock", [{"caches_to_mock": [
|
|
@@ -626,7 +623,6 @@ def test_multihop_receiver_on_success(vo, did_factory, root_account, caches_mock
|
|
|
626
623
|
RECEIVER_GRACEFUL_STOP.clear()
|
|
627
624
|
|
|
628
625
|
|
|
629
|
-
@pytest.mark.skip(reason="Pending https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC4506150")
|
|
630
626
|
@skip_rse_tests_with_accounts
|
|
631
627
|
@pytest.mark.dirty(reason="leaves files in XRD containers")
|
|
632
628
|
@pytest.mark.noparallel(groups=[NoParallelGroups.XRD, NoParallelGroups.SUBMITTER, NoParallelGroups.RECEIVER, NoParallelGroups.POLLER])
|
|
@@ -696,7 +692,6 @@ def test_receiver_archiving(vo, did_factory, root_account, caches_mock, scitags_
|
|
|
696
692
|
RECEIVER_GRACEFUL_STOP.clear()
|
|
697
693
|
|
|
698
694
|
|
|
699
|
-
@pytest.mark.skip(reason="Pending https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC4506150")
|
|
700
695
|
@skip_rse_tests_with_accounts
|
|
701
696
|
@pytest.mark.noparallel(groups=[NoParallelGroups.PREPARER, NoParallelGroups.THROTTLER, NoParallelGroups.SUBMITTER, NoParallelGroups.POLLER])
|
|
702
697
|
@pytest.mark.parametrize("file_config_mock", [{
|
|
@@ -713,6 +708,10 @@ def test_preparer_throttler_submitter(rse_factory, did_factory, root_account, fi
|
|
|
713
708
|
|
|
714
709
|
for rse_id in all_rses:
|
|
715
710
|
rse_core.add_rse_attribute(rse_id, RseAttr.FTS, TEST_FTS_HOST)
|
|
711
|
+
# Disable checksum verification
|
|
712
|
+
# to avoid user-defining source and destination checksum for each transfer
|
|
713
|
+
# (required when using the mock protocol on FTS >= 3.14.1)
|
|
714
|
+
rse_core.add_rse_attribute(rse_id, RseAttr.VERIFY_CHECKSUM, False)
|
|
716
715
|
distance_core.add_distance(src_rse_id, dst_rse_id1, distance=10)
|
|
717
716
|
distance_core.add_distance(src_rse_id, dst_rse_id2, distance=10)
|
|
718
717
|
# Set limits only for one of the RSEs
|
|
@@ -1029,7 +1028,6 @@ def test_failed_transfers_to_mas_existing_replica(rse_factory, did_factory, root
|
|
|
1029
1028
|
assert rule_core.get_rule(rule2_id)['state'] == RuleState.STUCK
|
|
1030
1029
|
|
|
1031
1030
|
|
|
1032
|
-
@pytest.mark.skip(reason="Pending https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC4506150")
|
|
1033
1031
|
@skip_rse_tests_with_accounts
|
|
1034
1032
|
@pytest.mark.noparallel(groups=[NoParallelGroups.SUBMITTER, NoParallelGroups.POLLER, NoParallelGroups.FINISHER])
|
|
1035
1033
|
def test_lost_transfers(rse_factory, did_factory, root_account):
|
|
@@ -1045,11 +1043,21 @@ def test_lost_transfers(rse_factory, did_factory, root_account):
|
|
|
1045
1043
|
rse_core.add_rse_attribute(rse_id, RseAttr.FTS, TEST_FTS_HOST)
|
|
1046
1044
|
|
|
1047
1045
|
did = did_factory.upload_test_file(src_rse)
|
|
1046
|
+
replica = replica_core.get_replica(rse_id=src_rse_id, **did)
|
|
1048
1047
|
|
|
1049
1048
|
rule_core.add_rule(dids=[did], account=root_account, copies=1, rse_expression=dst_rse, grouping='ALL', weight=None, lifetime=None, locked=False, subscription_id=None)
|
|
1050
1049
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1050
|
+
class _FTSWrapper(FTSWrapper):
|
|
1051
|
+
@staticmethod
|
|
1052
|
+
def on_submit(file):
|
|
1053
|
+
# Set the correct checksum on both source and destination
|
|
1054
|
+
file['sources'] = [set_query_parameters(s_url, {'checksum': replica['adler32']}) for s_url in file['sources']]
|
|
1055
|
+
file['destinations'] = [set_query_parameters(d_url, {'checksum': replica['adler32']}) for d_url in file['destinations']]
|
|
1056
|
+
|
|
1057
|
+
with patch('rucio.core.transfer.TRANSFERTOOL_CLASSES_BY_NAME', new={'fts3': _FTSWrapper}):
|
|
1058
|
+
# Fake that the transfer is submitted and lost
|
|
1059
|
+
submitter(once=True, rses=[{'id': rse_id} for rse_id in all_rses], group_bulk=2, partition_wait_time=0, transfertype='single', filter_transfertool=None)
|
|
1060
|
+
|
|
1053
1061
|
request = request_core.get_request_by_did(rse_id=dst_rse_id, **did)
|
|
1054
1062
|
__update_request(request['id'], external_id='some-fake-random-id')
|
|
1055
1063
|
|
|
@@ -1064,7 +1072,8 @@ def test_lost_transfers(rse_factory, did_factory, root_account):
|
|
|
1064
1072
|
# The source ranking must not be updated for submission failures and lost transfers
|
|
1065
1073
|
request = request_core.get_request_by_did(rse_id=dst_rse_id, **did)
|
|
1066
1074
|
assert __get_source(request_id=request['id'], src_rse_id=src_rse_id, **did).ranking == 0
|
|
1067
|
-
|
|
1075
|
+
with patch('rucio.core.transfer.TRANSFERTOOL_CLASSES_BY_NAME', new={'fts3': _FTSWrapper}):
|
|
1076
|
+
submitter(once=True, rses=[{'id': rse_id} for rse_id in all_rses], group_bulk=2, partition_wait_time=0, transfertype='single', filter_transfertool=None)
|
|
1068
1077
|
replica = __wait_for_replica_transfer(dst_rse_id=dst_rse_id, **did)
|
|
1069
1078
|
assert replica['state'] == ReplicaState.AVAILABLE
|
|
1070
1079
|
|
|
@@ -1430,7 +1439,6 @@ def test_multi_vo_certificates(file_config_mock, rse_factory, did_factory, scope
|
|
|
1430
1439
|
assert sorted(certs_used_by_poller) == ['DEFAULT_DUMMY_CERT', 'NEW_VO_DUMMY_CERT']
|
|
1431
1440
|
|
|
1432
1441
|
|
|
1433
|
-
@pytest.mark.skip(reason="Pending https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC4506150")
|
|
1434
1442
|
@skip_rse_tests_with_accounts
|
|
1435
1443
|
@pytest.mark.noparallel(groups=[NoParallelGroups.SUBMITTER, NoParallelGroups.POLLER, NoParallelGroups.FINISHER])
|
|
1436
1444
|
@pytest.mark.parametrize("core_config_mock", [
|
|
@@ -1474,6 +1482,7 @@ def test_two_multihops_same_intermediate_rse(rse_factory, did_factory, root_acco
|
|
|
1474
1482
|
all_rses = [rse1_id, rse2_id, rse3_id, rse4_id, rse5_id, rse6_id, rse7_id]
|
|
1475
1483
|
for rse_id in all_rses:
|
|
1476
1484
|
rse_core.add_rse_attribute(rse_id, RseAttr.FTS, TEST_FTS_HOST)
|
|
1485
|
+
rse_core.add_rse_attribute(rse_id, RseAttr.VERIFY_CHECKSUM, False)
|
|
1477
1486
|
rse_core.set_rse_limits(rse_id=rse_id, name='MinFreeSpace', value=1)
|
|
1478
1487
|
rse_core.set_rse_usage(rse_id=rse_id, source='storage', used=1, free=0)
|
|
1479
1488
|
distance_core.add_distance(rse1_id, rse2_id, distance=10)
|
|
@@ -1562,7 +1571,6 @@ def test_two_multihops_same_intermediate_rse(rse_factory, did_factory, root_acco
|
|
|
1562
1571
|
assert dict_stats[rse2_id][rse1_id]['bytes_done'] == 2
|
|
1563
1572
|
|
|
1564
1573
|
|
|
1565
|
-
@pytest.mark.skip(reason="Pending https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC4506150")
|
|
1566
1574
|
@skip_rse_tests_with_accounts
|
|
1567
1575
|
@pytest.mark.noparallel(groups=[NoParallelGroups.SUBMITTER, NoParallelGroups.POLLER])
|
|
1568
1576
|
def test_checksum_validation(rse_factory, did_factory, root_account):
|
|
@@ -1607,15 +1615,14 @@ def test_checksum_validation(rse_factory, did_factory, root_account):
|
|
|
1607
1615
|
# No common supported checksum between the source and destination rse. It will verify the destination rse checksum and fail
|
|
1608
1616
|
request = __wait_for_state_transition(dst_rse_id=dst_rse2_id, **did)
|
|
1609
1617
|
assert request['state'] == RequestState.FAILED
|
|
1610
|
-
assert 'User and destination
|
|
1618
|
+
assert 'User-defined and destination MD5 checksum do not match' in request['err_msg']
|
|
1611
1619
|
|
|
1612
|
-
# Common checksum exists between the two. It
|
|
1620
|
+
# Common checksum exists between the two. It It will fail early when checking the user-defined and destination checksums.
|
|
1613
1621
|
request = __wait_for_state_transition(dst_rse_id=dst_rse3_id, **did)
|
|
1614
|
-
assert '
|
|
1622
|
+
assert 'User-defined and destination ADLER32 checksum do not match' in request['err_msg']
|
|
1615
1623
|
assert request['state'] == RequestState.FAILED
|
|
1616
1624
|
|
|
1617
1625
|
|
|
1618
|
-
@pytest.mark.skip(reason="Pending https://cern.service-now.com/service-portal?id=ticket&table=incident&n=INC4506150")
|
|
1619
1626
|
@skip_rse_tests_with_accounts
|
|
1620
1627
|
@pytest.mark.needs_iam
|
|
1621
1628
|
@pytest.mark.noparallel(groups=[NoParallelGroups.XRD, NoParallelGroups.SUBMITTER, NoParallelGroups.RECEIVER])
|
|
@@ -431,6 +431,27 @@ class TestDidMetaExternalPostgresJSON:
|
|
|
431
431
|
postgres_json_meta.set_metadata(scope=mock_scope, name=did_name, key=meta_key, value=meta_value)
|
|
432
432
|
assert postgres_json_meta.get_metadata(scope=mock_scope, name=did_name)[meta_key] == meta_value
|
|
433
433
|
|
|
434
|
+
@pytest.mark.dirty
|
|
435
|
+
def test_delete_metadata(self, mock_scope, root_account, postgres_json_meta):
|
|
436
|
+
""" DID Meta (POSTGRES_JSON): delete DID meta """
|
|
437
|
+
|
|
438
|
+
did_name = did_name_generator('dataset')
|
|
439
|
+
meta_key1 = 'my_key_%s' % generate_uuid()
|
|
440
|
+
meta_value1 = 'my_value_%s' % generate_uuid()
|
|
441
|
+
meta_key2 = 'my_key_%s' % generate_uuid()
|
|
442
|
+
meta_value2 = 'my_value_%s' % generate_uuid()
|
|
443
|
+
add_did(scope=mock_scope, name=did_name, did_type='DATASET', account=root_account)
|
|
444
|
+
postgres_json_meta.set_metadata(scope=mock_scope, name=did_name, key=meta_key1, value=meta_value1)
|
|
445
|
+
postgres_json_meta.set_metadata(scope=mock_scope, name=did_name, key=meta_key2, value=meta_value2)
|
|
446
|
+
|
|
447
|
+
assert postgres_json_meta.get_metadata(scope=mock_scope, name=did_name)[meta_key1] == meta_value1
|
|
448
|
+
assert postgres_json_meta.get_metadata(scope=mock_scope, name=did_name)[meta_key2] == meta_value2
|
|
449
|
+
|
|
450
|
+
postgres_json_meta.delete_metadata(scope=mock_scope, name=did_name, key=meta_key2)
|
|
451
|
+
metadata = postgres_json_meta.get_metadata(scope=mock_scope, name=did_name)
|
|
452
|
+
assert metadata[meta_key1] == meta_value1
|
|
453
|
+
assert meta_key2 not in metadata
|
|
454
|
+
|
|
434
455
|
@pytest.mark.dirty
|
|
435
456
|
def test_list_did_meta(self, mock_scope, root_account, postgres_json_meta):
|
|
436
457
|
""" DID Meta (POSTGRES_JSON): List DID meta """
|
|
@@ -407,7 +407,7 @@ class TestGatewayExternalRepresentation:
|
|
|
407
407
|
def test_gateway_scope(self, vo, vo2, account_name, scope_name, scope):
|
|
408
408
|
""" SCOPE (Gateway): Test external representation of scopes """
|
|
409
409
|
|
|
410
|
-
out = list_scopes()
|
|
410
|
+
out = [s['scope'] for s in list_scopes()]
|
|
411
411
|
assert scope_name in out
|
|
412
412
|
if vo2:
|
|
413
413
|
assert scope.internal not in out
|
|
@@ -757,8 +757,8 @@ class TestMultiVoClients:
|
|
|
757
757
|
scope_client.add_scope('root', shr)
|
|
758
758
|
add_scope(new, 'root', 'root', vo=second_vo)
|
|
759
759
|
add_scope(shr, 'root', 'root', vo=second_vo)
|
|
760
|
-
scope_list_tst =
|
|
761
|
-
scope_list_new =
|
|
760
|
+
scope_list_tst = [s['scope'] for s in scope_client.list_scopes()]
|
|
761
|
+
scope_list_new = [s['scope'] for s in list_scopes(filter_={}, vo=second_vo)]
|
|
762
762
|
assert tst in scope_list_tst
|
|
763
763
|
assert new not in scope_list_tst
|
|
764
764
|
assert shr in scope_list_tst
|