rucio-clients 35.4.1__tar.gz → 35.6.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.

Files changed (188) hide show
  1. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/PKG-INFO +1 -1
  2. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/bin/rucio +20 -19
  3. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/exception.py +47 -12
  4. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/schema/__init__.py +4 -4
  5. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/vcsversion.py +3 -3
  6. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_replica_sorting.py +22 -1
  7. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_transfer_plugins.py +121 -72
  8. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/AUTHORS.rst +0 -0
  9. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/ChangeLog +0 -0
  10. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/LICENSE +0 -0
  11. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/MANIFEST.in +0 -0
  12. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/README.md +0 -0
  13. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/bin/rucio-admin +0 -0
  14. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/etc/rse-accounts.cfg.template +0 -0
  15. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/etc/rucio.cfg.atlas.client.template +0 -0
  16. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/etc/rucio.cfg.template +0 -0
  17. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/__init__.py +0 -0
  18. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/alembicrevision.py +0 -0
  19. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/__init__.py +0 -0
  20. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/accountclient.py +0 -0
  21. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/accountlimitclient.py +0 -0
  22. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/baseclient.py +0 -0
  23. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/client.py +0 -0
  24. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/configclient.py +0 -0
  25. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/credentialclient.py +0 -0
  26. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/didclient.py +0 -0
  27. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/diracclient.py +0 -0
  28. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/downloadclient.py +0 -0
  29. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/exportclient.py +0 -0
  30. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/fileclient.py +0 -0
  31. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/importclient.py +0 -0
  32. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/lifetimeclient.py +0 -0
  33. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/lockclient.py +0 -0
  34. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/metaconventionsclient.py +0 -0
  35. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/pingclient.py +0 -0
  36. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/replicaclient.py +0 -0
  37. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/requestclient.py +0 -0
  38. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/rseclient.py +0 -0
  39. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/ruleclient.py +0 -0
  40. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/scopeclient.py +0 -0
  41. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/subscriptionclient.py +0 -0
  42. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/touchclient.py +0 -0
  43. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/client/uploadclient.py +0 -0
  44. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/__init__.py +0 -0
  45. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/cache.py +0 -0
  46. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/config.py +0 -0
  47. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/constants.py +0 -0
  48. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/constraints.py +0 -0
  49. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/didtype.py +0 -0
  50. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/extra.py +0 -0
  51. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/logging.py +0 -0
  52. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/pcache.py +0 -0
  53. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/plugins.py +0 -0
  54. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/policy.py +0 -0
  55. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/schema/atlas.py +0 -0
  56. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/schema/belleii.py +0 -0
  57. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/schema/domatpc.py +0 -0
  58. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/schema/escape.py +0 -0
  59. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/schema/generic.py +0 -0
  60. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/schema/generic_multi_vo.py +0 -0
  61. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/schema/icecube.py +0 -0
  62. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/stomp_utils.py +0 -0
  63. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/stopwatch.py +0 -0
  64. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/test_rucio_server.py +0 -0
  65. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/types.py +0 -0
  66. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/common/utils.py +0 -0
  67. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/__init__.py +0 -0
  68. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/__init__.py +0 -0
  69. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/bittorrent.py +0 -0
  70. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/cache.py +0 -0
  71. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/dummy.py +0 -0
  72. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/gfal.py +0 -0
  73. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/globus.py +0 -0
  74. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/gsiftp.py +0 -0
  75. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/http_cache.py +0 -0
  76. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/mock.py +0 -0
  77. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/ngarc.py +0 -0
  78. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/posix.py +0 -0
  79. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/protocol.py +0 -0
  80. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/rclone.py +0 -0
  81. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/rfio.py +0 -0
  82. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/srm.py +0 -0
  83. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/ssh.py +0 -0
  84. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/storm.py +0 -0
  85. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/webdav.py +0 -0
  86. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/protocols/xrootd.py +0 -0
  87. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/rse/rsemanager.py +0 -0
  88. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio/version.py +0 -0
  89. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/lib/rucio_clients.egg-info/SOURCES.txt +0 -0
  90. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/pylintrc +0 -0
  91. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/pyproject.toml +0 -0
  92. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/requirements/requirements.client.txt +0 -0
  93. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/setup.cfg +0 -0
  94. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/setup.py +0 -0
  95. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/setuputil.py +0 -0
  96. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_abacus_account.py +0 -0
  97. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_abacus_collection_replica.py +0 -0
  98. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_abacus_rse.py +0 -0
  99. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_account.py +0 -0
  100. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_account_limits.py +0 -0
  101. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_archive.py +0 -0
  102. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_auditor.py +0 -0
  103. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_auditor_hdfs.py +0 -0
  104. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_auditor_srmdumps.py +0 -0
  105. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_authentication.py +0 -0
  106. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_automatix.py +0 -0
  107. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_bad_replica.py +0 -0
  108. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_bb8.py +0 -0
  109. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_belleii.py +0 -0
  110. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_bin_rucio.py +0 -0
  111. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_boolean.py +0 -0
  112. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_clients.py +0 -0
  113. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_common_types.py +0 -0
  114. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_config.py +0 -0
  115. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_conveyor.py +0 -0
  116. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_conveyor_submitter.py +0 -0
  117. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_counter.py +0 -0
  118. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_credential.py +0 -0
  119. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_curl.py +0 -0
  120. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_daemons.py +0 -0
  121. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_dataset_replicas.py +0 -0
  122. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_db.py +0 -0
  123. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_did.py +0 -0
  124. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_did_meta_plugins.py +0 -0
  125. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_didtype.py +0 -0
  126. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_download.py +0 -0
  127. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_dumper.py +0 -0
  128. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_dumper_consistency.py +0 -0
  129. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_dumper_data_model.py +0 -0
  130. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_dumper_path_parsing.py +0 -0
  131. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_filter_engine.py +0 -0
  132. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_gateway_external_representation.py +0 -0
  133. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_heartbeat.py +0 -0
  134. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_hermes.py +0 -0
  135. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_identity.py +0 -0
  136. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_impl_upload_download.py +0 -0
  137. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_import_export.py +0 -0
  138. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_judge_cleaner.py +0 -0
  139. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_judge_evaluator.py +0 -0
  140. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_judge_injector.py +0 -0
  141. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_judge_repairer.py +0 -0
  142. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_lifetime.py +0 -0
  143. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_message.py +0 -0
  144. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_meta_conventions.py +0 -0
  145. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_meta_did.py +0 -0
  146. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_module_import.py +0 -0
  147. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_monitor.py +0 -0
  148. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_multi_vo.py +0 -0
  149. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_naming_convention.py +0 -0
  150. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_oauthmanager.py +0 -0
  151. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_oidc.py +0 -0
  152. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_permission.py +0 -0
  153. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_pfns.py +0 -0
  154. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_ping.py +0 -0
  155. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_preparer.py +0 -0
  156. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_qos.py +0 -0
  157. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_quarantined_replica.py +0 -0
  158. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_reaper.py +0 -0
  159. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_redirect.py +0 -0
  160. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_replica.py +0 -0
  161. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_replica_recoverer.py +0 -0
  162. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_request.py +0 -0
  163. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_root_proxy.py +0 -0
  164. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse.py +0 -0
  165. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_expression_parser.py +0 -0
  166. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_lfn2path.py +0 -0
  167. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_protocol_gfal2.py +0 -0
  168. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_protocol_gfal2_impl.py +0 -0
  169. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_protocol_posix.py +0 -0
  170. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_protocol_rclone.py +0 -0
  171. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_protocol_rsync.py +0 -0
  172. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_protocol_srm.py +0 -0
  173. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_protocol_ssh.py +0 -0
  174. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_protocol_webdav.py +0 -0
  175. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_protocol_xrootd.py +0 -0
  176. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rse_selector.py +0 -0
  177. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rucio_server.py +0 -0
  178. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_rule.py +0 -0
  179. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_scope.py +0 -0
  180. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_subscription.py +0 -0
  181. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_throttler.py +0 -0
  182. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_tpc.py +0 -0
  183. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_trace.py +0 -0
  184. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_transfer.py +0 -0
  185. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_undertaker.py +0 -0
  186. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_upload.py +0 -0
  187. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tests/test_utils.py +0 -0
  188. {rucio_clients-35.4.1 → rucio_clients-35.6.0}/tools/merge_rucio_configs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: rucio-clients
3
- Version: 35.4.1
3
+ Version: 35.6.0
4
4
  Summary: Rucio Client Lite Package
5
5
  Home-page: https://rucio.cern.ch/
6
6
  Author: Rucio
@@ -412,7 +412,7 @@ def list_file_replicas(args):
412
412
  pfn_dir, dst_dir = args.link.split(':')
413
413
  if args.rses:
414
414
  for replica, rse in itertools.product(replicas, rses):
415
- if rse in list(replica['rses'].keys()) and replica['rses'][rse]:
415
+ if replica['rses'].get(rse):
416
416
  for pfn in replica['rses'][rse]:
417
417
  os.symlink(dst_dir + pfn.rsplit(pfn_dir)[-1], replica['name'])
418
418
  else:
@@ -423,16 +423,17 @@ def list_file_replicas(args):
423
423
  os.symlink(dst_dir + pfn.rsplit(pfn_dir)[-1], replica['name'])
424
424
  elif args.pfns:
425
425
  if args.rses:
426
- for replica, rse in itertools.product(replicas, rses):
427
- if rse in list(replica['rses'].keys()) and replica['rses'][rse]:
428
- for pfn in replica['rses'][rse]:
426
+ for replica in replicas:
427
+ for pfn in replica['pfns']:
428
+ rse = replica['pfns'][pfn]['rse']
429
+ if replica['rses'].get(rse):
429
430
  print(pfn)
430
431
  else:
431
432
  for replica in replicas:
432
- for rse in replica['rses']:
433
+ for pfn in replica['pfns']:
434
+ rse = replica['pfns'][pfn]['rse']
433
435
  if replica['rses'][rse]:
434
- for pfn in replica['rses'][rse]:
435
- print(pfn)
436
+ print(pfn)
436
437
  else:
437
438
  if args.all_states:
438
439
  header = ['SCOPE', 'NAME', 'FILESIZE', 'ADLER32', '(STATE) RSE: REPLICA']
@@ -440,18 +441,18 @@ def list_file_replicas(args):
440
441
  header = ['SCOPE', 'NAME', 'FILESIZE', 'ADLER32', 'RSE: REPLICA']
441
442
  for replica in replicas:
442
443
  if 'bytes' in replica:
443
- for rse in replica['rses']:
444
- for pfn in replica['rses'][rse]:
445
- if args.all_states:
446
- rse_string = '({2}) {0}: {1}'.format(rse, pfn, ReplicaState[replica['states'][rse]].value)
447
- else:
448
- rse_string = '{0}: {1}'.format(rse, pfn)
449
- if args.rses:
450
- for selected_rse in rses:
451
- if rse == selected_rse:
452
- table.append([replica['scope'], replica['name'], sizefmt(replica['bytes'], args.human), replica['adler32'], rse_string])
453
- else:
454
- table.append([replica['scope'], replica['name'], sizefmt(replica['bytes'], args.human), replica['adler32'], rse_string])
444
+ for pfn in replica['pfns']:
445
+ rse = replica['pfns'][pfn]['rse']
446
+ if args.all_states:
447
+ rse_string = '({2}) {0}: {1}'.format(rse, pfn, ReplicaState[replica['states'][rse]].value)
448
+ else:
449
+ rse_string = '{0}: {1}'.format(rse, pfn)
450
+ if args.rses:
451
+ for selected_rse in rses:
452
+ if rse == selected_rse:
453
+ table.append([replica['scope'], replica['name'], sizefmt(replica['bytes'], args.human), replica['adler32'], rse_string])
454
+ else:
455
+ table.append([replica['scope'], replica['name'], sizefmt(replica['bytes'], args.human), replica['adler32'], rse_string])
455
456
  print(tabulate(table, tablefmt=tablefmt, headers=header, disable_numparse=True))
456
457
  return SUCCESS
457
458
 
@@ -955,13 +955,22 @@ class NoDistance(RucioException):
955
955
  self.error_code = 92
956
956
 
957
957
 
958
- class PolicyPackageNotFound(RucioException):
958
+ class PolicyPackageBaseException(RucioException):
959
+ """
960
+ Base exception for policy package errors.
961
+ """
962
+ def __init__(self, package: str, *args):
963
+ super(PolicyPackageBaseException, self).__init__(*args)
964
+ self.package = package
965
+
966
+
967
+ class PolicyPackageNotFound(PolicyPackageBaseException):
959
968
  """
960
969
  The policy package specified in the config file was not found
961
970
  """
962
- def __init__(self, *args):
963
- super(PolicyPackageNotFound, self).__init__(*args)
964
- self._message = 'The specified policy package was not found'
971
+ def __init__(self, package: str, *args):
972
+ super(PolicyPackageNotFound, self).__init__(package, *args)
973
+ self._message = 'The specified policy package %s was not found' % self.package
965
974
  self.error_code = 93
966
975
 
967
976
 
@@ -1055,13 +1064,19 @@ class MetadataSchemaMismatchError(RucioException):
1055
1064
  self.error_code = 102
1056
1065
 
1057
1066
 
1058
- class PolicyPackageVersionError(RucioException):
1067
+ class PolicyPackageVersionError(PolicyPackageBaseException):
1059
1068
  """
1060
1069
  Policy package is not compatible with this version of Rucio.
1061
1070
  """
1062
- def __init__(self, package, *args):
1063
- super(PolicyPackageVersionError, self).__init__(*args)
1064
- self._message = 'Policy package %s is not compatible with this Rucio version' % package
1071
+ def __init__(self, package: str, rucio_version: str, supported_versions: list[str], *args):
1072
+ super(PolicyPackageVersionError, self).__init__(package, *args)
1073
+ self.rucio_version = rucio_version
1074
+ self.supported_versions = supported_versions
1075
+ self._message = 'Policy package %s is not compatible with this Rucio version.\nRucio version: %s\nVersions supported by the package: %s' % (
1076
+ self.package,
1077
+ self.rucio_version,
1078
+ self.supported_versions
1079
+ )
1065
1080
  self.error_code = 103
1066
1081
 
1067
1082
 
@@ -1096,13 +1111,13 @@ class SortingAlgorithmNotSupported(RucioException):
1096
1111
  self.error_code = 106
1097
1112
 
1098
1113
 
1099
- class ErrorLoadingPolicyPackage(RucioException):
1114
+ class ErrorLoadingPolicyPackage(PolicyPackageBaseException):
1100
1115
  """
1101
1116
  An error occurred while loading the policy package.
1102
1117
  """
1103
- def __init__(self, *args):
1104
- super(ErrorLoadingPolicyPackage, self).__init__(*args)
1105
- self._message = 'An error occurred while loading the specified policy package'
1118
+ def __init__(self, package: str, *args):
1119
+ super(ErrorLoadingPolicyPackage, self).__init__(package, *args)
1120
+ self._message = 'An error occurred while loading the policy package %s' % self.package
1106
1121
  self.error_code = 107
1107
1122
 
1108
1123
 
@@ -1114,3 +1129,23 @@ class TraceValidationSchemaNotFound(RucioException):
1114
1129
  super(TraceValidationSchemaNotFound, self).__init__(*args, **kwargs)
1115
1130
  self._message = 'Trace validation schema not found.'
1116
1131
  self.error_code = 108
1132
+
1133
+
1134
+ class PolicyPackageIsNotVersioned(PolicyPackageBaseException):
1135
+ """
1136
+ Policy package does not contain version information.
1137
+ """
1138
+ def __init__(self, package: str, *args):
1139
+ super(PolicyPackageIsNotVersioned, self).__init__(package, *args)
1140
+ self._message = 'Policy package %s does not include information about which Rucio versions it supports.' % self.package
1141
+ self.error_code = 109
1142
+
1143
+
1144
+ class UnsupportedMetadataPlugin(RucioException):
1145
+ """
1146
+ Raised when attempting to use a metadata plugin that is not enabled on the server.
1147
+ """
1148
+ def __init__(self, *args):
1149
+ super(UnsupportedMetadataPlugin, self).__init__(*args)
1150
+ self._message = "The requested metadata plugin is not enabled on the server."
1151
+ self.error_code = 110
@@ -61,9 +61,9 @@ if not multivo:
61
61
  try:
62
62
  module = importlib.import_module(POLICY)
63
63
  except ModuleNotFoundError:
64
- raise exception.PolicyPackageNotFound('Module ' + POLICY + ' not found')
64
+ raise exception.PolicyPackageNotFound(POLICY)
65
65
  except ImportError:
66
- raise exception.ErrorLoadingPolicyPackage('An error occurred while loading module ' + POLICY)
66
+ raise exception.ErrorLoadingPolicyPackage(POLICY)
67
67
 
68
68
  schema_modules["def"] = module
69
69
  scope_name_regexps.append(module.SCOPE_NAME_REGEXP)
@@ -93,9 +93,9 @@ def load_schema_for_vo(vo: str) -> None:
93
93
  try:
94
94
  module = importlib.import_module(POLICY)
95
95
  except ModuleNotFoundError:
96
- raise exception.PolicyPackageNotFound('Module ' + POLICY + ' not found')
96
+ raise exception.PolicyPackageNotFound(POLICY)
97
97
  except ImportError:
98
- raise exception.ErrorLoadingPolicyPackage('An error occurred while loading module ' + POLICY)
98
+ raise exception.ErrorLoadingPolicyPackage(POLICY)
99
99
 
100
100
  schema_modules[vo] = module
101
101
 
@@ -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': '35.4.1',
7
+ 'version': '35.6.0',
8
8
  'branch_nick': 'release-35-LTS',
9
- 'revision_id': 'b041c5990126a6987d2f884680869fc93b609acc',
10
- 'revno': 13162
9
+ 'revision_id': '76a17347408868f403f602b5bf626c9744620829',
10
+ 'revno': 13190
11
11
  }
@@ -22,6 +22,7 @@ from urllib.parse import urlparse
22
22
  import geoip2.database
23
23
  import pytest
24
24
 
25
+ import rucio.core.config as core_config
25
26
  from rucio.common.config import config_get
26
27
  from rucio.common.constants import RseAttr
27
28
  from rucio.common.utils import parse_replicas_from_string
@@ -448,7 +449,7 @@ def test_not_sorting_lan_replicas(vo, rest_client, auth_token, protocols_setup,
448
449
  @pytest.mark.noparallel(reason='fails when run in parallel')
449
450
  @pytest.mark.parametrize("content_type", [Mime.METALINK, Mime.JSON_STREAM])
450
451
  def test_sort_geoip_address_not_found_error(vo, rest_client, auth_token, protocols_setup, content_type):
451
- """Replicas: test sorting via geoip with ignoring geoip errors."""
452
+ """Replicas: test sorting via geoip with ignoring geoip errors (and without)."""
452
453
 
453
454
  class MockedGeoIPError(Exception):
454
455
  def __init__(self, *args):
@@ -479,6 +480,26 @@ def test_sort_geoip_address_not_found_error(vo, rest_client, auth_token, protoco
479
480
 
480
481
  get_geoip_db_mock.assert_called()
481
482
 
483
+ # now set config to not ignore errors
484
+ core_config.set("core", "geoip_ignore_error", False)
485
+
486
+ # invalidate cache for __get_distance so that __get_geoip_db is called
487
+ replica_sorter.REGION.invalidate()
488
+
489
+ with mock.patch('rucio.core.replica_sorter.__geoip_db', side_effect=fake_get_geoip_db) as get_geoip_db_mock:
490
+ response = rest_client.post(
491
+ '/replicas/list',
492
+ headers=headers(auth(auth_token), vohdr(vo), accept(content_type)),
493
+ json=data
494
+ )
495
+ # this time the call should fail
496
+ assert response.status_code != 200
497
+
498
+ get_geoip_db_mock.assert_called()
499
+
500
+ # reset to ignore errors for other tests
501
+ core_config.set("core", "geoip_ignore_error", True)
502
+
482
503
 
483
504
  @pytest.mark.noparallel(reason='fails when run in parallel, replicas should not be changed')
484
505
  def test_get_sorted_list_replicas_no_metalink(vo, rest_client, auth_token, protocols_setup, mock_scope):
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import logging
16
+ from unittest.mock import MagicMock
16
17
 
17
18
  import pytest
18
19
 
@@ -24,6 +25,7 @@ from rucio.core.topology import Topology
24
25
  from rucio.core.transfer import ProtocolFactory, build_transfer_paths
25
26
  from rucio.db.sqla.session import get_session
26
27
  from rucio.transfertool.fts3 import FTS3Transfertool, build_job_params
28
+ from rucio.transfertool.fts3_plugins import FTS3TapeMetadataPlugin
27
29
 
28
30
  mock_session = get_session()
29
31
 
@@ -31,9 +33,14 @@ MAX_POLL_WAIT_SECONDS = 60
31
33
  TEST_FTS_HOST = "https://fts:8446"
32
34
 
33
35
 
34
- def _make_transfer_path(did, rse_factory, root_account):
36
+ def _make_transfer_path(
37
+ did,
38
+ rse_factory,
39
+ root_account,
40
+ dst_rse_is_tape: bool = True
41
+ ):
35
42
  _, src_rse_id = rse_factory.make_mock_rse()
36
- dst_rse, dst_rse_id = rse_factory.make_mock_rse()
43
+ dst_rse, dst_rse_id = rse_factory.make_mock_rse(rse_type="TAPE" if dst_rse_is_tape else "DISK")
37
44
  all_rses = [src_rse_id, dst_rse_id]
38
45
  distance_core.add_distance(src_rse_id, dst_rse_id, distance=1)
39
46
 
@@ -102,7 +109,7 @@ def test_scheduling_hints(file_config_mock, did_factory, rse_factory, root_accou
102
109
  assert len(job_params["archive_metadata"].keys()) == 1
103
110
  generated_scheduling_hints = job_params["archive_metadata"]["scheduling_hints"]
104
111
 
105
- expected_scheduling_hints = {"priority": "100"}
112
+ expected_scheduling_hints = {"priority": 100}
106
113
  assert expected_scheduling_hints == generated_scheduling_hints
107
114
 
108
115
 
@@ -144,65 +151,117 @@ def test_activity_missing(file_config_mock, did_factory, rse_factory, root_accou
144
151
  assert "archive_metadata" in job_params
145
152
  generated_scheduling_hints = job_params["archive_metadata"]["scheduling_hints"]
146
153
 
147
- expected_scheduling_hints = {"priority": "20"}
154
+ expected_scheduling_hints = {"priority": 20}
148
155
  assert expected_scheduling_hints == generated_scheduling_hints
149
156
 
150
157
 
151
- @pytest.mark.parametrize("file_config_mock", [
152
- {
153
- "overrides": [
154
- ("transfers", "fts3tape_metadata_plugins", "test")
155
- ]
156
- }
157
- ], indirect=True)
158
- def test_collocation_hints(file_config_mock, did_factory, rse_factory, root_account):
159
- """For a mock collocation algorithm, it can produce the 4 levels of hints required for each did"""
158
+ class TestCollocationHints:
159
+ class TestCollocationPlugin(FTS3TapeMetadataPlugin):
160
+ def __init__(self) -> None:
161
+ self.register(
162
+ 'test',
163
+ func=lambda x: self._test_collocation(x))
164
+ super().__init__('test')
160
165
 
161
- mock_did = did_factory.random_file_did()
162
- transfer_path = _make_transfer_path(mock_did, rse_factory, root_account)
166
+ def _test_collocation(self, hints: dict[str, str]) -> dict[str, dict]:
167
+ return {"collocation_hints": {"0": "", "1": "", "2": "", "3": ""}}
163
168
 
164
- # Mock Transfer Tool
165
- fts3_tool = FTS3Transfertool(TEST_FTS_HOST)
169
+ TestCollocationPlugin()
166
170
 
167
- job_params = build_job_params(
168
- transfer_path=transfer_path,
169
- bring_online=None,
170
- default_lifetime=None,
171
- archive_timeout_override=None,
172
- max_time_in_queue=None,
173
- logger=logging.log,
174
- )
171
+ @pytest.mark.parametrize("file_config_mock", [
172
+ {
173
+ "overrides": [
174
+ ("transfers", "fts3tape_metadata_plugins", "test")
175
+ ]
176
+ }
177
+ ], indirect=True)
178
+ def test_collocation_hints(self, file_config_mock, did_factory, rse_factory, root_account):
179
+ """For a mock collocation algorithm, it can produce the 4 levels of hints required for each did"""
180
+
181
+ mock_did = did_factory.random_file_did()
182
+ transfer_path = _make_transfer_path(mock_did, rse_factory, root_account)
183
+
184
+ # Mock Transfer Tool
185
+ fts3_tool = FTS3Transfertool(TEST_FTS_HOST)
186
+
187
+ job_params = build_job_params(
188
+ transfer_path=transfer_path,
189
+ bring_online=None,
190
+ default_lifetime=None,
191
+ archive_timeout_override=None,
192
+ max_time_in_queue=None,
193
+ logger=logging.log,
194
+ )
195
+
196
+ # Get the job params used for each transfer
197
+ job_params = fts3_tool._file_from_transfer(transfer_path[0], job_params)
175
198
 
176
- # Get the job params used for each transfer
177
- job_params = fts3_tool._file_from_transfer(transfer_path[0], job_params)
199
+ expected_collocation_hints = {
200
+ "collocation_hints": {
201
+ "0": "",
202
+ "1": "",
203
+ "2": "",
204
+ "3": "",
205
+ }
206
+ }
207
+
208
+ assert "archive_metadata" in job_params
209
+ generated_collocation_hints = job_params["archive_metadata"]["collocation_hints"]
210
+
211
+ assert (
212
+ expected_collocation_hints["collocation_hints"] == generated_collocation_hints
213
+ )
178
214
 
179
- expected_collocation_hints = {
180
- "collocation_hints": {
181
- "0": "",
182
- "1": "",
183
- "2": "",
184
- "3": "",
215
+ @pytest.mark.parametrize("file_config_mock", [
216
+ {
217
+ "overrides": [
218
+ ("transfers", "fts3tape_metadata_plugins", "activity, test")
219
+ ]
185
220
  }
186
- }
221
+ ], indirect=True)
222
+ def test_multiple_plugin_concat(self, file_config_mock, did_factory, rse_factory, root_account):
223
+ """When multiple plugins are used (like priority and collocation), both logics are applied"""
224
+
225
+ mock_did = did_factory.random_file_did()
226
+ transfer_path = _make_transfer_path(mock_did, rse_factory, root_account)
227
+
228
+ # Mock Transfer Tool
229
+ fts3_tool = FTS3Transfertool(TEST_FTS_HOST)
230
+
231
+ job_params = build_job_params(
232
+ transfer_path=transfer_path,
233
+ bring_online=None,
234
+ default_lifetime=None,
235
+ archive_timeout_override=None,
236
+ max_time_in_queue=None,
237
+ logger=logging.log,
238
+ )
239
+
240
+ # Get the job params used for each transfer
241
+ job_params = fts3_tool._file_from_transfer(transfer_path[0], job_params)
242
+ expected_hints = {
243
+ "scheduling_hints": {"priority": 20},
244
+ "collocation_hints": {"0": "", "1": "", "2": "", "3": ""},
245
+ }
246
+ assert "archive_metadata" in job_params
187
247
 
188
- assert "archive_metadata" in job_params
189
- generated_collocation_hints = job_params["archive_metadata"]["collocation_hints"]
248
+ generated_collocation_hints = job_params["archive_metadata"]["collocation_hints"]
249
+ assert expected_hints["collocation_hints"] == generated_collocation_hints
190
250
 
191
- assert (
192
- expected_collocation_hints["collocation_hints"] == generated_collocation_hints
193
- )
251
+ generated_scheduling_hints = job_params["archive_metadata"]["scheduling_hints"]
252
+ assert expected_hints["scheduling_hints"] == generated_scheduling_hints
194
253
 
195
254
 
196
255
  @pytest.mark.parametrize("file_config_mock", [
197
256
  {
198
257
  "overrides": [
199
- ("transfers", "fts3tape_metadata_plugins", "activity, test")
258
+ ("transfers", "metadata_byte_limit", "4"),
259
+ ("transfers", "fts3tape_metadata_plugins", "def")
260
+
200
261
  ]
201
262
  }
202
263
  ], indirect=True)
203
- def test_multiple_plugin_concat(file_config_mock, did_factory, rse_factory, root_account):
204
- """When multiple plugins are used (like priority and collocation), both logics are applied"""
205
-
264
+ def test_transfer_over_limit(file_config_mock, did_factory, rse_factory, root_account):
206
265
  mock_did = did_factory.random_file_did()
207
266
  transfer_path = _make_transfer_path(mock_did, rse_factory, root_account)
208
267
 
@@ -218,31 +277,15 @@ def test_multiple_plugin_concat(file_config_mock, did_factory, rse_factory, root
218
277
  logger=logging.log,
219
278
  )
220
279
 
221
- # Get the job params used for each transfer
222
- job_params = fts3_tool._file_from_transfer(transfer_path[0], job_params)
223
- expected_hints = {
224
- "scheduling_hints": {"priority": "20"},
225
- "collocation_hints": {"0": "", "1": "", "2": "", "3": ""},
226
- }
227
- assert "archive_metadata" in job_params
228
-
229
- generated_collocation_hints = job_params["archive_metadata"]["collocation_hints"]
230
- assert expected_hints["collocation_hints"] == generated_collocation_hints
280
+ from rucio.common.exception import InvalidRequest
231
281
 
232
- expected_schedule_hints = job_params["archive_metadata"]["scheduling_hints"]
233
- assert expected_hints["scheduling_hints"] == expected_schedule_hints
282
+ with pytest.raises(InvalidRequest):
283
+ job_params = fts3_tool._file_from_transfer(transfer_path[0], job_params)
234
284
 
235
285
 
236
- @pytest.mark.parametrize("file_config_mock", [
237
- {
238
- "overrides": [
239
- ("transfers", "metadata_byte_limit", "4"),
240
- ("transfers", "fts3tape_metadata_plugins", "def")
286
+ def test_include_none_by_default(did_factory, rse_factory, root_account):
287
+ # When there is not plugin specified in the config, do not include any archive metadata
241
288
 
242
- ]
243
- }
244
- ], indirect=True)
245
- def test_transfer_over_limit(file_config_mock, did_factory, rse_factory, root_account):
246
289
  mock_did = did_factory.random_file_did()
247
290
  transfer_path = _make_transfer_path(mock_did, rse_factory, root_account)
248
291
 
@@ -258,21 +301,25 @@ def test_transfer_over_limit(file_config_mock, did_factory, rse_factory, root_ac
258
301
  logger=logging.log,
259
302
  )
260
303
 
261
- from rucio.common.exception import InvalidRequest
262
-
263
- with pytest.raises(InvalidRequest):
264
- job_params = fts3_tool._file_from_transfer(transfer_path[0], job_params)
304
+ job_params = fts3_tool._file_from_transfer(transfer_path[0], job_params)
305
+ assert "archive_metadata" not in job_params
265
306
 
266
307
 
267
- def test_include_none_by_default(did_factory, rse_factory, root_account):
268
- # When there is not plugin specified in the config, do not include any archive metadata
308
+ def test_no_metadata_if_dest_is_not_tape(did_factory, rse_factory, root_account):
309
+ """
310
+ If the destination RSE is not tape,
311
+ no tape metadata plugin should run,
312
+ and no archive metadata should be included.
313
+ """
269
314
 
270
315
  mock_did = did_factory.random_file_did()
271
- transfer_path = _make_transfer_path(mock_did, rse_factory, root_account)
316
+ mock_metadata_plugin = MagicMock()
317
+ transfer_path = _make_transfer_path(mock_did, rse_factory, root_account, dst_rse_is_tape=False)
272
318
 
273
- # Mock Transfer Tool
274
319
  fts3_tool = FTS3Transfertool(TEST_FTS_HOST)
275
320
 
321
+ fts3_tool.tape_metadata_plugins = [mock_metadata_plugin] # type: ignore
322
+
276
323
  job_params = build_job_params(
277
324
  transfer_path=transfer_path,
278
325
  bring_online=None,
@@ -283,4 +330,6 @@ def test_include_none_by_default(did_factory, rse_factory, root_account):
283
330
  )
284
331
 
285
332
  job_params = fts3_tool._file_from_transfer(transfer_path[0], job_params)
333
+
334
+ assert not mock_metadata_plugin.called
286
335
  assert "archive_metadata" not in job_params
File without changes
File without changes
File without changes