rucio 35.7.0__py3-none-any.whl → 37.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rucio might be problematic. Click here for more details.

Files changed (266) hide show
  1. rucio/alembicrevision.py +1 -1
  2. rucio/{daemons/c3po/collectors → cli}/__init__.py +1 -0
  3. rucio/cli/account.py +216 -0
  4. rucio-35.7.0.data/scripts/rucio → rucio/cli/bin_legacy/rucio.py +769 -486
  5. rucio-35.7.0.data/scripts/rucio-admin → rucio/cli/bin_legacy/rucio_admin.py +476 -423
  6. rucio/cli/command.py +272 -0
  7. rucio/cli/config.py +72 -0
  8. rucio/cli/did.py +191 -0
  9. rucio/cli/download.py +128 -0
  10. rucio/cli/lifetime_exception.py +33 -0
  11. rucio/cli/replica.py +162 -0
  12. rucio/cli/rse.py +293 -0
  13. rucio/cli/rule.py +158 -0
  14. rucio/cli/scope.py +40 -0
  15. rucio/cli/subscription.py +73 -0
  16. rucio/cli/upload.py +60 -0
  17. rucio/cli/utils.py +226 -0
  18. rucio/client/accountclient.py +0 -1
  19. rucio/client/baseclient.py +33 -24
  20. rucio/client/client.py +45 -1
  21. rucio/client/didclient.py +5 -3
  22. rucio/client/downloadclient.py +6 -8
  23. rucio/client/replicaclient.py +0 -2
  24. rucio/client/richclient.py +317 -0
  25. rucio/client/rseclient.py +4 -4
  26. rucio/client/uploadclient.py +26 -12
  27. rucio/common/bittorrent.py +234 -0
  28. rucio/common/cache.py +66 -29
  29. rucio/common/checksum.py +168 -0
  30. rucio/common/client.py +122 -0
  31. rucio/common/config.py +22 -35
  32. rucio/common/constants.py +61 -3
  33. rucio/common/didtype.py +72 -24
  34. rucio/common/dumper/__init__.py +45 -38
  35. rucio/common/dumper/consistency.py +75 -30
  36. rucio/common/dumper/data_models.py +63 -19
  37. rucio/common/dumper/path_parsing.py +19 -8
  38. rucio/common/exception.py +65 -8
  39. rucio/common/extra.py +5 -10
  40. rucio/common/logging.py +13 -13
  41. rucio/common/pcache.py +8 -7
  42. rucio/common/plugins.py +59 -27
  43. rucio/common/policy.py +12 -3
  44. rucio/common/schema/__init__.py +84 -34
  45. rucio/common/schema/generic.py +0 -17
  46. rucio/common/schema/generic_multi_vo.py +0 -17
  47. rucio/common/test_rucio_server.py +12 -6
  48. rucio/common/types.py +132 -52
  49. rucio/common/utils.py +93 -643
  50. rucio/core/account_limit.py +14 -12
  51. rucio/core/authentication.py +2 -2
  52. rucio/core/config.py +23 -42
  53. rucio/core/credential.py +14 -15
  54. rucio/core/did.py +5 -1
  55. rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
  56. rucio/core/did_meta_plugins/filter_engine.py +62 -3
  57. rucio/core/did_meta_plugins/json_meta.py +2 -2
  58. rucio/core/did_meta_plugins/mongo_meta.py +43 -30
  59. rucio/core/did_meta_plugins/postgres_meta.py +75 -39
  60. rucio/core/identity.py +6 -5
  61. rucio/core/importer.py +4 -3
  62. rucio/core/lifetime_exception.py +2 -2
  63. rucio/core/lock.py +8 -7
  64. rucio/core/message.py +6 -0
  65. rucio/core/monitor.py +30 -29
  66. rucio/core/naming_convention.py +2 -2
  67. rucio/core/nongrid_trace.py +2 -2
  68. rucio/core/oidc.py +11 -9
  69. rucio/core/permission/__init__.py +79 -37
  70. rucio/core/permission/generic.py +1 -7
  71. rucio/core/permission/generic_multi_vo.py +1 -7
  72. rucio/core/quarantined_replica.py +4 -3
  73. rucio/core/replica.py +464 -139
  74. rucio/core/replica_sorter.py +55 -59
  75. rucio/core/request.py +34 -32
  76. rucio/core/rse.py +301 -97
  77. rucio/core/rse_counter.py +1 -2
  78. rucio/core/rse_expression_parser.py +7 -7
  79. rucio/core/rse_selector.py +9 -7
  80. rucio/core/rule.py +41 -40
  81. rucio/core/rule_grouping.py +42 -40
  82. rucio/core/scope.py +5 -4
  83. rucio/core/subscription.py +26 -28
  84. rucio/core/topology.py +11 -11
  85. rucio/core/trace.py +2 -2
  86. rucio/core/transfer.py +29 -15
  87. rucio/core/volatile_replica.py +4 -3
  88. rucio/daemons/atropos/atropos.py +1 -1
  89. rucio/daemons/auditor/__init__.py +2 -2
  90. rucio/daemons/auditor/srmdumps.py +6 -6
  91. rucio/daemons/automatix/automatix.py +32 -21
  92. rucio/daemons/badreplicas/necromancer.py +2 -2
  93. rucio/daemons/bb8/nuclei_background_rebalance.py +1 -1
  94. rucio/daemons/bb8/t2_background_rebalance.py +1 -1
  95. rucio/daemons/common.py +15 -25
  96. rucio/daemons/conveyor/finisher.py +2 -2
  97. rucio/daemons/conveyor/poller.py +18 -28
  98. rucio/daemons/conveyor/receiver.py +2 -2
  99. rucio/daemons/conveyor/stager.py +1 -0
  100. rucio/daemons/conveyor/submitter.py +3 -3
  101. rucio/daemons/hermes/hermes.py +91 -30
  102. rucio/daemons/judge/evaluator.py +2 -2
  103. rucio/daemons/oauthmanager/oauthmanager.py +3 -3
  104. rucio/daemons/reaper/dark_reaper.py +7 -3
  105. rucio/daemons/reaper/reaper.py +12 -16
  106. rucio/daemons/rsedecommissioner/config.py +1 -1
  107. rucio/daemons/rsedecommissioner/profiles/generic.py +5 -4
  108. rucio/daemons/rsedecommissioner/profiles/types.py +7 -6
  109. rucio/daemons/rsedecommissioner/rse_decommissioner.py +1 -1
  110. rucio/daemons/storage/consistency/actions.py +8 -6
  111. rucio/daemons/tracer/kronos.py +4 -4
  112. rucio/db/sqla/constants.py +5 -0
  113. rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +4 -4
  114. rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
  115. rucio/db/sqla/models.py +157 -154
  116. rucio/db/sqla/session.py +58 -27
  117. rucio/db/sqla/types.py +2 -2
  118. rucio/db/sqla/util.py +2 -2
  119. rucio/gateway/account.py +18 -12
  120. rucio/gateway/account_limit.py +137 -60
  121. rucio/gateway/authentication.py +18 -12
  122. rucio/gateway/config.py +30 -20
  123. rucio/gateway/credential.py +9 -10
  124. rucio/gateway/did.py +70 -53
  125. rucio/gateway/dirac.py +6 -4
  126. rucio/gateway/exporter.py +3 -2
  127. rucio/gateway/heartbeat.py +6 -4
  128. rucio/gateway/identity.py +36 -51
  129. rucio/gateway/importer.py +3 -2
  130. rucio/gateway/lifetime_exception.py +3 -2
  131. rucio/gateway/meta_conventions.py +17 -6
  132. rucio/gateway/permission.py +4 -1
  133. rucio/gateway/quarantined_replica.py +3 -2
  134. rucio/gateway/replica.py +31 -22
  135. rucio/gateway/request.py +27 -18
  136. rucio/gateway/rse.py +69 -37
  137. rucio/gateway/rule.py +46 -26
  138. rucio/gateway/scope.py +3 -2
  139. rucio/gateway/subscription.py +14 -11
  140. rucio/gateway/vo.py +12 -8
  141. rucio/rse/__init__.py +3 -3
  142. rucio/rse/protocols/bittorrent.py +11 -1
  143. rucio/rse/protocols/cache.py +0 -11
  144. rucio/rse/protocols/dummy.py +0 -11
  145. rucio/rse/protocols/gfal.py +14 -9
  146. rucio/rse/protocols/globus.py +1 -1
  147. rucio/rse/protocols/http_cache.py +1 -1
  148. rucio/rse/protocols/posix.py +2 -2
  149. rucio/rse/protocols/protocol.py +84 -317
  150. rucio/rse/protocols/rclone.py +2 -1
  151. rucio/rse/protocols/rfio.py +10 -1
  152. rucio/rse/protocols/ssh.py +2 -1
  153. rucio/rse/protocols/storm.py +2 -13
  154. rucio/rse/protocols/webdav.py +74 -30
  155. rucio/rse/protocols/xrootd.py +2 -1
  156. rucio/rse/rsemanager.py +170 -53
  157. rucio/rse/translation.py +260 -0
  158. rucio/tests/common.py +23 -13
  159. rucio/tests/common_server.py +26 -9
  160. rucio/transfertool/bittorrent.py +15 -14
  161. rucio/transfertool/bittorrent_driver.py +5 -7
  162. rucio/transfertool/bittorrent_driver_qbittorrent.py +9 -8
  163. rucio/transfertool/fts3.py +20 -16
  164. rucio/transfertool/mock.py +2 -3
  165. rucio/vcsversion.py +4 -4
  166. rucio/version.py +7 -0
  167. rucio/web/rest/flaskapi/v1/accounts.py +17 -3
  168. rucio/web/rest/flaskapi/v1/auth.py +5 -5
  169. rucio/web/rest/flaskapi/v1/credentials.py +3 -2
  170. rucio/web/rest/flaskapi/v1/dids.py +21 -15
  171. rucio/web/rest/flaskapi/v1/identities.py +33 -9
  172. rucio/web/rest/flaskapi/v1/redirect.py +5 -4
  173. rucio/web/rest/flaskapi/v1/replicas.py +12 -8
  174. rucio/web/rest/flaskapi/v1/rses.py +15 -4
  175. rucio/web/rest/flaskapi/v1/traces.py +56 -19
  176. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic.ini.template +1 -1
  177. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic_offline.ini.template +1 -1
  178. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +3 -2
  179. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.template +3 -19
  180. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +1 -18
  181. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/requirements.server.txt +97 -68
  182. rucio-37.0.0.data/scripts/rucio +133 -0
  183. rucio-37.0.0.data/scripts/rucio-admin +97 -0
  184. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-atropos +2 -2
  185. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-auditor +2 -1
  186. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-automatix +2 -2
  187. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-client +17 -10
  188. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-receiver +1 -0
  189. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-kronos +1 -0
  190. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos +2 -2
  191. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos-temporary-expiration +2 -2
  192. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-necromancer +2 -2
  193. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-reaper +6 -6
  194. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-transmogrifier +2 -2
  195. rucio-37.0.0.dist-info/METADATA +92 -0
  196. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/RECORD +237 -243
  197. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/licenses/AUTHORS.rst +3 -0
  198. rucio/common/schema/atlas.py +0 -413
  199. rucio/common/schema/belleii.py +0 -408
  200. rucio/common/schema/domatpc.py +0 -401
  201. rucio/common/schema/escape.py +0 -426
  202. rucio/common/schema/icecube.py +0 -406
  203. rucio/core/permission/atlas.py +0 -1348
  204. rucio/core/permission/belleii.py +0 -1077
  205. rucio/core/permission/escape.py +0 -1078
  206. rucio/daemons/c3po/algorithms/__init__.py +0 -13
  207. rucio/daemons/c3po/algorithms/simple.py +0 -134
  208. rucio/daemons/c3po/algorithms/t2_free_space.py +0 -128
  209. rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +0 -130
  210. rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +0 -294
  211. rucio/daemons/c3po/c3po.py +0 -371
  212. rucio/daemons/c3po/collectors/agis.py +0 -108
  213. rucio/daemons/c3po/collectors/free_space.py +0 -81
  214. rucio/daemons/c3po/collectors/jedi_did.py +0 -57
  215. rucio/daemons/c3po/collectors/mock_did.py +0 -51
  216. rucio/daemons/c3po/collectors/network_metrics.py +0 -71
  217. rucio/daemons/c3po/collectors/workload.py +0 -112
  218. rucio/daemons/c3po/utils/__init__.py +0 -13
  219. rucio/daemons/c3po/utils/dataset_cache.py +0 -50
  220. rucio/daemons/c3po/utils/expiring_dataset_cache.py +0 -56
  221. rucio/daemons/c3po/utils/expiring_list.py +0 -62
  222. rucio/daemons/c3po/utils/popularity.py +0 -85
  223. rucio/daemons/c3po/utils/timeseries.py +0 -89
  224. rucio/rse/protocols/gsiftp.py +0 -92
  225. rucio-35.7.0.data/scripts/rucio-c3po +0 -85
  226. rucio-35.7.0.dist-info/METADATA +0 -72
  227. /rucio/{daemons/c3po → cli/bin_legacy}/__init__.py +0 -0
  228. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
  229. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
  230. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
  231. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
  232. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
  233. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
  234. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
  235. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
  236. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
  237. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/bootstrap.py +0 -0
  238. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
  239. {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/reset_database.py +0 -0
  240. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-account +0 -0
  241. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-collection-replica +0 -0
  242. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-rse +0 -0
  243. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-bb8 +0 -0
  244. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-consumer +0 -0
  245. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-finisher +0 -0
  246. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-poller +0 -0
  247. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-preparer +0 -0
  248. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-stager +0 -0
  249. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-submitter +0 -0
  250. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-throttler +0 -0
  251. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dark-reaper +0 -0
  252. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dumper +0 -0
  253. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-follower +0 -0
  254. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-hermes +0 -0
  255. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-cleaner +0 -0
  256. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-evaluator +0 -0
  257. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-injector +0 -0
  258. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-repairer +0 -0
  259. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-oauth-manager +0 -0
  260. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-replica-recoverer +0 -0
  261. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-rse-decommissioner +0 -0
  262. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-storage-consistency-actions +0 -0
  263. {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-undertaker +0 -0
  264. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/WHEEL +0 -0
  265. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/licenses/LICENSE +0 -0
  266. {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/top_level.txt +0 -0
@@ -23,7 +23,6 @@ import logging
23
23
  import re
24
24
  import threading
25
25
  import time
26
- from collections.abc import Mapping, Sequence
27
26
  from itertools import groupby
28
27
  from typing import TYPE_CHECKING, Any, Optional
29
28
 
@@ -31,11 +30,10 @@ from requests.exceptions import RequestException
31
30
  from sqlalchemy.exc import DatabaseError
32
31
 
33
32
  import rucio.db.sqla.util
34
- from rucio.common.config import config_get, config_get_bool
33
+ from rucio.common.config import config_get, config_get_bool, config_get_float
35
34
  from rucio.common.exception import DatabaseException, TransferToolTimeout, TransferToolWrongAnswer
36
35
  from rucio.common.logging import setup_logging
37
36
  from rucio.common.stopwatch import Stopwatch
38
- from rucio.common.types import InternalAccount, LoggerFunction
39
37
  from rucio.common.utils import dict_chunks
40
38
  from rucio.core import request as request_core
41
39
  from rucio.core import transfer as transfer_core
@@ -44,12 +42,14 @@ from rucio.core.topology import ExpiringObjectCache, Topology
44
42
  from rucio.daemons.common import ProducerConsumerDaemon, db_workqueue
45
43
  from rucio.db.sqla.constants import MYSQL_LOCK_WAIT_TIMEOUT_EXCEEDED, ORACLE_DEADLOCK_DETECTED_REGEX, ORACLE_RESOURCE_BUSY_REGEX, RequestState, RequestType
46
44
  from rucio.transfertool.fts3 import FTS3Transfertool
47
- from rucio.transfertool.transfertool import Transfertool
48
45
 
49
46
  if TYPE_CHECKING:
47
+ from collections.abc import Mapping, Sequence
50
48
  from types import FrameType
51
49
 
50
+ from rucio.common.types import LoggerFunction
52
51
  from rucio.daemons.common import HeartbeatHandler
52
+ from rucio.transfertool.transfertool import Transfertool
53
53
 
54
54
  GRACEFUL_STOP = threading.Event()
55
55
  METRICS = MetricManager(module=__name__)
@@ -62,7 +62,7 @@ FILTER_TRANSFERTOOL = config_get('conveyor', 'filter_transfertool', False, None)
62
62
  def _fetch_requests(
63
63
  db_bulk: int,
64
64
  older_than: int,
65
- activity_shares: Optional[Mapping[str, float]],
65
+ activity_shares: Optional['Mapping[str, float]'],
66
66
  transfertool: Optional[str],
67
67
  filter_transfertool: Optional[str],
68
68
  cached_topology: Optional[ExpiringObjectCache],
@@ -116,9 +116,9 @@ def _handle_requests(
116
116
  timeout: Optional[int],
117
117
  transfertool: str,
118
118
  transfer_stats_manager: request_core.TransferStatsManager,
119
- oidc_account: Optional[str],
119
+ oidc_support: bool,
120
120
  *,
121
- logger: LoggerFunction = logging.log,
121
+ logger: "LoggerFunction" = logging.log,
122
122
  ) -> None:
123
123
  transfs.sort(key=lambda t: (t['external_host'] or '',
124
124
  t['scope'].vo if multi_vo else '',
@@ -136,15 +136,9 @@ def _handle_requests(
136
136
 
137
137
  transfertool_kwargs = {}
138
138
  if transfertool_cls.external_name == FTS3Transfertool.external_name:
139
- account = None
140
- if oidc_account:
141
- if vo:
142
- account = InternalAccount(oidc_account, vo=vo)
143
- else:
144
- account = InternalAccount(oidc_account)
145
139
  transfertool_kwargs.update({
146
140
  'vo': vo,
147
- 'oidc_account': account,
141
+ 'oidc_support': oidc_support,
148
142
  })
149
143
 
150
144
  transfertool_obj = transfertool_cls(external_host=external_host, **transfertool_kwargs)
@@ -161,12 +155,12 @@ def _handle_requests(
161
155
 
162
156
  def poller(
163
157
  once: bool = False,
164
- activities: Optional[Sequence[str]] = None,
158
+ activities: Optional['Sequence[str]'] = None,
165
159
  sleep_time: int = 60,
166
160
  fts_bulk: int = 100,
167
161
  db_bulk: int = 1000,
168
162
  older_than: int = 60,
169
- activity_shares: Optional[Mapping[str, float]] = None,
163
+ activity_shares: Optional['Mapping[str, float]'] = None,
170
164
  partition_wait_time: int = 10,
171
165
  transfertool: Optional[str] = TRANSFER_TOOL,
172
166
  filter_transfertool: Optional[str] = FILTER_TRANSFERTOOL,
@@ -176,13 +170,9 @@ def poller(
176
170
  """
177
171
  Main loop to check the status of a transfer primitive with a transfertool.
178
172
  """
179
-
180
- timeout = config_get('conveyor', 'poll_timeout', default=None, raise_exception=False)
181
- if timeout:
182
- timeout = float(timeout)
183
-
173
+ timeout = config_get_float('conveyor', 'poll_timeout', default=None, raise_exception=False)
184
174
  multi_vo = config_get_bool('common', 'multi_vo', False, None)
185
- oidc_account = config_get('conveyor', 'poller_oidc_account', False, None)
175
+ oidc_support = config_get_bool('conveyor', 'poller_oidc_support', default=False, raise_exception=False)
186
176
 
187
177
  executable = DAEMON_NAME
188
178
 
@@ -227,7 +217,7 @@ def poller(
227
217
  fts_bulk=fts_bulk,
228
218
  multi_vo=multi_vo,
229
219
  timeout=timeout, # type: ignore (unclear if timeout is meant to be int or float)
230
- oidc_account=oidc_account,
220
+ oidc_support=oidc_support,
231
221
  transfertool=transfertool, # type: ignore (transfertool is not None)
232
222
  transfer_stats_manager=transfer_stats_manager,
233
223
  )
@@ -251,7 +241,7 @@ def stop(signum: Optional[int] = None, frame: Optional["FrameType"] = None) -> N
251
241
  def run(
252
242
  once: bool = False,
253
243
  sleep_time: int = 60,
254
- activities: Optional[Sequence[str]] = None,
244
+ activities: Optional['Sequence[str]'] = None,
255
245
  fts_bulk: int = 100,
256
246
  db_bulk: int = 1000,
257
247
  older_than: int = 60,
@@ -301,8 +291,8 @@ def run(
301
291
 
302
292
 
303
293
  def poll_transfers(
304
- transfertool_obj: Transfertool,
305
- transfers_by_eid: Mapping[str, Mapping[str, Any]],
294
+ transfertool_obj: 'Transfertool',
295
+ transfers_by_eid: 'Mapping[str, Mapping[str, Any]]',
306
296
  transfer_stats_manager: request_core.TransferStatsManager,
307
297
  timeout: "Optional[int]" = None,
308
298
  logger: "LoggerFunction" = logging.log
@@ -328,8 +318,8 @@ def poll_transfers(
328
318
 
329
319
 
330
320
  def _poll_transfers(
331
- transfertool_obj: Transfertool,
332
- transfers_by_eid: Mapping[str, Mapping[str, Any]],
321
+ transfertool_obj: 'Transfertool',
322
+ transfers_by_eid: 'Mapping[str, Mapping[str, Any]]',
333
323
  transfer_stats_manager: request_core.TransferStatsManager,
334
324
  timeout: "Optional[int]" = None,
335
325
  logger: "LoggerFunction" = logging.log
@@ -28,7 +28,7 @@ import stomp
28
28
 
29
29
  import rucio.db.sqla.util
30
30
  from rucio.common import exception
31
- from rucio.common.config import config_get, config_get_bool, config_get_int
31
+ from rucio.common.config import config_get, config_get_bool, config_get_int, config_get_list
32
32
  from rucio.common.logging import setup_logging
33
33
  from rucio.common.policy import get_policy
34
34
  from rucio.core import request as request_core
@@ -134,7 +134,7 @@ def receiver(
134
134
  brokers_alias = []
135
135
  brokers_resolved = []
136
136
  try:
137
- brokers_alias = [b.strip() for b in config_get('messaging-fts3', 'brokers').split(',')]
137
+ brokers_alias = config_get_list('messaging-fts3', 'brokers')
138
138
  except Exception:
139
139
  raise Exception('Could not load brokers from configuration')
140
140
 
@@ -36,6 +36,7 @@ if TYPE_CHECKING:
36
36
 
37
37
  from rucio.common.types import RSESettingsDict
38
38
 
39
+
39
40
  METRICS = MetricManager(module=__name__)
40
41
  GRACEFUL_STOP = threading.Event()
41
42
  DAEMON_NAME = 'conveyor-stager'
@@ -17,7 +17,6 @@ Conveyor transfer submitter is a daemon to manage non-tape file transfers.
17
17
  """
18
18
  import logging
19
19
  import threading
20
- from collections.abc import Mapping
21
20
  from typing import TYPE_CHECKING, Optional
22
21
 
23
22
  import rucio.db.sqla.util
@@ -37,6 +36,7 @@ from rucio.transfertool.fts3 import FTS3Transfertool
37
36
  from rucio.transfertool.globus import GlobusTransferTool
38
37
 
39
38
  if TYPE_CHECKING:
39
+ from collections.abc import Mapping
40
40
  from types import FrameType
41
41
 
42
42
  from rucio.common.types import LoggerFunction, RSESettingsDict
@@ -114,7 +114,7 @@ def _fetch_requests(
114
114
 
115
115
 
116
116
  def _handle_requests(
117
- batch: tuple[Topology, Mapping[str, RequestWithSources]],
117
+ batch: tuple[Topology, 'Mapping[str, RequestWithSources]'],
118
118
  *,
119
119
  transfertools: list[str],
120
120
  schemes: Optional[list[str]],
@@ -301,7 +301,7 @@ def submitter(
301
301
  heartbeat_handler=heartbeat_handler,
302
302
  )
303
303
 
304
- def _consumer(batch: tuple[Topology, Mapping[str, RequestWithSources]]) -> None:
304
+ def _consumer(batch: tuple[Topology, 'Mapping[str, RequestWithSources]']) -> None:
305
305
  return _handle_requests(
306
306
  batch,
307
307
  transfertools=transfertools,
@@ -114,10 +114,7 @@ def setup_activemq(
114
114
  brokers_alias = []
115
115
  brokers_resolved = []
116
116
  try:
117
- brokers_alias = [
118
- broker.strip()
119
- for broker in config_get("messaging-hermes", "brokers").split(",")
120
- ]
117
+ brokers_alias = config_get_list("messaging-hermes", "brokers")
121
118
  except:
122
119
  raise Exception("Could not load brokers from configuration")
123
120
 
@@ -408,7 +405,7 @@ def submit_to_elastic(
408
405
 
409
406
  def aggregate_to_influx(
410
407
  messages: "Iterable[dict[str, Any]]",
411
- bin_size: int,
408
+ bin_size: str,
412
409
  endpoint: str,
413
410
  logger: "LoggerFunction"
414
411
  ) -> int:
@@ -517,6 +514,69 @@ def aggregate_to_influx(
517
514
  return 204
518
515
 
519
516
 
517
+ def build_message_dict(
518
+ bulk: int,
519
+ thread: int,
520
+ total_threads: int,
521
+ message_dict: dict[str, list[dict[str, Any]]],
522
+ logger: "LoggerFunction",
523
+ service: Optional[str] = None,
524
+ ) -> None:
525
+ """
526
+ Retrieves messages from the database and builds a dictionary with the keys being the services, and the values a list of the messages (built up of dictionary / json information)
527
+
528
+ :param bulk: Integer for number of messages to retrieve.
529
+ :param thread: Passed to thread in retrieve_messages for Identifier of the caller thread as an integer.
530
+ :param total_threads: Passed to total_threads for Maximum number of threads as an integer.
531
+ :param message_dict: Either empty dictionary to be built, or build upon when using query_by_service.
532
+ :param logger: The logger object.
533
+ :param service: When passed, only returns messages table for this specific service.
534
+
535
+ :returns: None, but builds on the dictionary message_dict passed to this fuction (for when querying multiple services).
536
+ """
537
+ start_time = time.time()
538
+ messages = retrieve_messages(
539
+ bulk=bulk,
540
+ old_mode=False,
541
+ thread=thread,
542
+ total_threads=total_threads,
543
+ service_filter=service,
544
+ )
545
+
546
+ if messages:
547
+ if service is not None:
548
+ # query_by_service dictionary build behaviour
549
+ message_dict[service] = messages.copy()
550
+ logger(
551
+ logging.DEBUG,
552
+ "Retrieved %i messages retrieved in %s seconds for %s service.",
553
+ len(messages),
554
+ time.time() - start_time,
555
+ service,
556
+ )
557
+
558
+ else:
559
+ # default dictionary build behaviour
560
+ for message in messages:
561
+ service = message["services"]
562
+ if service is not None:
563
+ if service not in message_dict:
564
+ message_dict[service] = []
565
+ message_dict[service].append(message)
566
+ logger(
567
+ logging.DEBUG,
568
+ "Retrieved %i messages retrieved in %s seconds",
569
+ len(messages),
570
+ time.time() - start_time,
571
+ )
572
+ else:
573
+ logger(
574
+ logging.INFO,
575
+ "No messages retrieved in %s seconds",
576
+ time.time() - start_time,
577
+ )
578
+
579
+
520
580
  def hermes(once: bool = False, bulk: int = 1000, sleep_time: int = 10) -> None:
521
581
  """
522
582
  Creates a Hermes Worker that can submit messages to different services (InfluXDB, ElasticSearch, ActiveMQ)
@@ -571,7 +631,6 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
571
631
  )
572
632
  except Exception as err:
573
633
  logger(logging.ERROR, str(err))
574
- conns = None
575
634
  if "activemq" in services_list:
576
635
  try:
577
636
  conns, destination, username, password, use_ssl = setup_activemq(logger)
@@ -585,30 +644,31 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
585
644
 
586
645
  worker_number, total_workers, logger = heartbeat_handler.live()
587
646
  message_dict = {}
588
- message_ids = []
589
- start_time = time.time()
590
- messages = retrieve_messages(
591
- bulk=bulk,
592
- old_mode=False,
593
- thread=worker_number,
594
- total_threads=total_workers,
595
- )
596
-
597
- to_delete = []
598
- if messages:
599
- for message in messages:
600
- service = message["services"]
601
- if service not in message_dict:
602
- message_dict[service] = []
603
- message_dict[service].append(message)
604
- message_ids.append(message["id"])
605
- logger(
606
- logging.DEBUG,
607
- "Retrieved %i messages retrieved in %s seconds",
608
- len(messages),
609
- time.time() - start_time,
647
+ query_by_service = config_get_bool("hermes", "query_by_service", default=False)
648
+
649
+ # query_by_service is a toggleable behaviour switch between collecting bulk number of messages across all services when false, to collecting bulk messages from each service when true.
650
+ if query_by_service:
651
+ for service in services_list:
652
+ build_message_dict(
653
+ bulk=bulk,
654
+ thread=worker_number,
655
+ total_threads=total_workers,
656
+ message_dict=message_dict,
657
+ logger=logger,
658
+ service=service,
659
+ )
660
+ else:
661
+ build_message_dict(
662
+ bulk=bulk,
663
+ thread=worker_number,
664
+ total_threads=total_workers,
665
+ message_dict=message_dict,
666
+ logger=logger
610
667
  )
611
668
 
669
+ if message_dict:
670
+ to_delete = []
671
+
612
672
  if "influx" in message_dict and influx_endpoint:
613
673
  # For influxDB, bulk submission, either everything succeeds or fails
614
674
  t_time = time.time()
@@ -685,12 +745,12 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
685
745
  except Exception as error:
686
746
  logger(logging.ERROR, "Error sending email : %s", str(error))
687
747
 
688
- if "activemq" in message_dict and conns:
748
+ if "activemq" in message_dict:
689
749
  t_time = time.time()
690
750
  try:
691
751
  messages_sent = deliver_to_activemq(
692
752
  messages=message_dict["activemq"],
693
- conns=conns,
753
+ conns=conns, # type: ignore (argument could be None)
694
754
  destination=destination, # type: ignore (argument could be None)
695
755
  username=username, # type: ignore (argument could be None)
696
756
  password=password, # type: ignore (argument could be None)
@@ -717,6 +777,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
717
777
  "updated_at": message["created_at"],
718
778
  "payload": str(message["payload"]),
719
779
  "event_type": message["event_type"],
780
+ "services": message["services"]
720
781
  }
721
782
  for message in to_delete
722
783
  ]
@@ -91,9 +91,9 @@ def run_once(
91
91
  dids = get_updated_dids(total_workers=total_workers,
92
92
  worker_number=worker_number,
93
93
  limit=did_limit,
94
- blocked_dids=[(InternalScope(key[0], fromExternal=False), key[1]) for key in paused_dids])
94
+ blocked_dids=[(InternalScope(key[0], from_external=False), key[1]) for key in paused_dids])
95
95
  logger(logging.DEBUG, 'index query time %f fetch size is %d (%d blocked)', time.time() - start, len(dids),
96
- len([(InternalScope(key[0], fromExternal=False), key[1]) for key in paused_dids]))
96
+ len([(InternalScope(key[0], from_external=False), key[1]) for key in paused_dids]))
97
97
 
98
98
  # If the list is empty, sent the worker to sleep
99
99
  if not dids:
@@ -53,7 +53,7 @@ graceful_stop = threading.Event()
53
53
  DAEMON_NAME = 'oauth-manager'
54
54
 
55
55
 
56
- def OAuthManager(once: bool = False, max_rows: int = 100, sleep_time: int = 300) -> None:
56
+ def oauth_manager(once: bool = False, max_rows: int = 100, sleep_time: int = 300) -> None:
57
57
  """
58
58
  Main loop to delete all expired tokens, refresh tokens eligible
59
59
  for refresh and delete all expired OAuth session parameters.
@@ -178,10 +178,10 @@ def run(once: bool = False, threads: int = 1, max_rows: int = 100, sleep_time: i
178
178
  raise DatabaseException('Database was not updated, daemon won\'t start')
179
179
 
180
180
  if once:
181
- OAuthManager(once, max_rows, sleep_time)
181
+ oauth_manager(once, max_rows, sleep_time)
182
182
  else:
183
183
  logging.info('OAuth Manager starting %s threads', str(threads))
184
- threads = [threading.Thread(target=OAuthManager,
184
+ threads = [threading.Thread(target=oauth_manager,
185
185
  kwargs={'once': once,
186
186
  'max_rows': max_rows,
187
187
  'sleep_time': sleep_time}) for i in range(0, threads)]
@@ -44,6 +44,7 @@ if TYPE_CHECKING:
44
44
  from types import FrameType
45
45
  from typing import Optional
46
46
 
47
+ from rucio.common.types import LFNDict
47
48
  from rucio.daemons.common import HeartbeatHandler
48
49
 
49
50
  logging.getLogger("requests").setLevel(logging.CRITICAL)
@@ -120,10 +121,13 @@ def run_once(
120
121
  if replica['scope']:
121
122
  scope = replica['scope'].external
122
123
  try:
124
+ lfn: "LFNDict" = {
125
+ 'scope': scope,
126
+ 'name': replica['name'],
127
+ 'path': replica['path']
128
+ }
123
129
  pfn = str(list(rsemgr.lfns2pfns(rse_settings=rse_info,
124
- lfns=[{'scope': scope,
125
- 'name': replica['name'],
126
- 'path': replica['path']}],
130
+ lfns=[lfn],
127
131
  operation='delete',
128
132
  scheme=scheme).values())[0])
129
133
  logger(logging.INFO, 'Deletion ATTEMPT of %s:%s as %s on %s', scope, replica['name'], pfn, rse)
@@ -12,9 +12,9 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- '''
15
+ """
16
16
  Reaper is a daemon to manage file deletion.
17
- '''
17
+ """
18
18
 
19
19
  import concurrent.futures.thread # noqa (https://github.com/rucio/rucio/issues/6548)
20
20
 
@@ -33,7 +33,7 @@ from dogpile.cache.api import NoValue
33
33
  from sqlalchemy.exc import DatabaseError, IntegrityError
34
34
 
35
35
  import rucio.db.sqla.util
36
- from rucio.common.cache import make_region_memcached
36
+ from rucio.common.cache import MemcacheRegion
37
37
  from rucio.common.config import config_get_bool, config_get_int
38
38
  from rucio.common.constants import RseAttr
39
39
  from rucio.common.exception import DatabaseException, ReplicaNotFound, ReplicaUnAvailable, ResourceTemporaryUnavailable, RSEAccessDenied, RSENotFound, RSEProtocolNotSupported, ServiceUnavailable, SourceNotFound, VONotFound
@@ -57,12 +57,12 @@ if TYPE_CHECKING:
57
57
  from collections.abc import Iterable, Sequence
58
58
  from types import FrameType
59
59
 
60
- from rucio.common.types import LoggerFunction
60
+ from rucio.common.types import LFNDict, LoggerFunction
61
61
  from rucio.daemons.common import HeartbeatHandler
62
62
 
63
63
  GRACEFUL_STOP = threading.Event()
64
64
  METRICS = MetricManager(module=__name__)
65
- REGION = make_region_memcached(expiration_time=600)
65
+ REGION = MemcacheRegion(expiration_time=600)
66
66
  DAEMON_NAME = 'reaper'
67
67
 
68
68
  EXCLUDED_RSE_GAUGE = METRICS.gauge('excluded_rses.{rse}', documentation='Temporarly excluded RSEs')
@@ -474,7 +474,7 @@ def run_once(
474
474
 
475
475
  rses_to_process = get_rses_to_process(rses, include_rses, exclude_rses, vos)
476
476
  if not rses_to_process:
477
- logger(logging.ERROR, 'Reaper: No RSEs found. Will sleep for 30 seconds')
477
+ logger(logging.WARNING, 'Reaper: No RSEs found, sleeping')
478
478
  return must_sleep
479
479
  else:
480
480
  rses_to_process = [RseData(id_=rse['id'], name=rse['rse'], columns=rse) for rse in rses_to_process]
@@ -632,8 +632,13 @@ def _run_once(
632
632
  del_start_time = time.time()
633
633
  for replica in file_replicas:
634
634
  try:
635
+ lfn: "LFNDict" = {
636
+ 'scope': replica['scope'].external,
637
+ 'name': replica['name'],
638
+ 'path': replica['path']
639
+ }
635
640
  replica['pfn'] = str(list(rsemgr.lfns2pfns(rse_settings=rse.info,
636
- lfns=[{'scope': replica['scope'].external, 'name': replica['name'], 'path': replica['path']}],
641
+ lfns=[lfn],
637
642
  operation='delete', scheme=scheme).values())[0])
638
643
  except (ReplicaUnAvailable, ReplicaNotFound) as error:
639
644
  logger(logging.WARNING, 'Failed get pfn UNAVAILABLE replica %s:%s on %s with error %s', replica['scope'], replica['name'], rse.name, str(error))
@@ -690,7 +695,6 @@ def run(
690
695
 
691
696
  :param threads: The total number of workers.
692
697
  :param chunk_size: The size of chunk for deletion.
693
- :param threads_per_worker: Total number of threads created by each worker.
694
698
  :param once: If True, only runs one iteration of the main loop.
695
699
  :param greedy: If True, delete right away replicas with tombstone.
696
700
  :param rses: List of RSEs the reaper should work against.
@@ -711,14 +715,6 @@ def run(
711
715
  if rucio.db.sqla.util.is_old_db():
712
716
  raise DatabaseException('Database was not updated, daemon won\'t start')
713
717
 
714
- logging.log(logging.INFO, 'main: starting processes')
715
- rses_to_process = get_rses_to_process(rses, include_rses, exclude_rses, vos)
716
- if not rses_to_process:
717
- logging.log(logging.ERROR, 'Reaper: No RSEs found. Exiting.')
718
- return
719
-
720
- logging.log(logging.INFO, 'Reaper: This instance will work on RSEs: %s', ', '.join([rse['rse'] for rse in rses_to_process]))
721
-
722
718
  logging.log(logging.INFO, 'starting reaper threads')
723
719
  threads_list = [threading.Thread(target=reaper, kwargs={'once': once,
724
720
  'rses': rses,
@@ -75,7 +75,7 @@ def set_status(
75
75
  :param rse_id: RSE ID.
76
76
  :param status: RSE decommissioning status.
77
77
  """
78
- config = attr_to_config(get_rse_attribute(rse_id, RseAttr.DECOMMISSION))
78
+ config = attr_to_config(get_rse_attribute(rse_id, RseAttr.DECOMMISSION)) # type: ignore (get_rse_attribute could return None)
79
79
  config['status'] = status
80
80
  # add_rse_attribute can handle updating existing entries too
81
81
  add_rse_attribute(rse_id, RseAttr.DECOMMISSION, config_to_attr(config))
@@ -14,7 +14,6 @@
14
14
 
15
15
  """Generic decommissioning profiles."""
16
16
  import logging
17
- from collections.abc import Callable, Iterable
18
17
  from datetime import datetime, timedelta
19
18
  from typing import TYPE_CHECKING, Any
20
19
 
@@ -32,6 +31,8 @@ from rucio.db.sqla.constants import ReplicaState
32
31
  from .types import DecommissioningProfile, HandlerOutcome
33
32
 
34
33
  if TYPE_CHECKING:
34
+ from collections.abc import Iterable
35
+
35
36
  from rucio.common.types import LoggerFunction
36
37
 
37
38
 
@@ -137,7 +138,7 @@ def _generic_discover(
137
138
  rse: dict[str, Any],
138
139
  *,
139
140
  logger: "LoggerFunction" = logging.log
140
- ) -> Iterable[dict[str, Any]]:
141
+ ) -> 'Iterable[dict[str, Any]]':
141
142
  """Discoverer function that calls the listing function from core.rule.
142
143
 
143
144
  :param rse: RSE table entry as a dictionary.
@@ -186,7 +187,7 @@ def _generic_finalize(
186
187
 
187
188
  def _process_replicas_with_no_locks(
188
189
  rse: dict[str, Any],
189
- replicas: Iterable[dict[str, Any]],
190
+ replicas: 'Iterable[dict[str, Any]]',
190
191
  limit: int = 0,
191
192
  *,
192
193
  logger: "LoggerFunction" = logging.log,
@@ -382,7 +383,7 @@ def _call_for_attention(
382
383
  rule: dict[str, Any],
383
384
  rse: dict[str, Any],
384
385
  *,
385
- logger: Callable[..., None] = logging.log
386
+ logger: "LoggerFunction" = logging.log
386
387
  ) -> HandlerOutcome:
387
388
  return HandlerOutcome.NEED_ATTENTION
388
389
 
@@ -14,12 +14,13 @@
14
14
 
15
15
  """Types used for profile definitions."""
16
16
  import logging
17
- from collections.abc import Callable, Iterable
18
17
  from dataclasses import dataclass
19
18
  from enum import Enum
20
19
  from typing import TYPE_CHECKING, Any
21
20
 
22
21
  if TYPE_CHECKING:
22
+ from collections.abc import Callable, Iterable
23
+
23
24
  from rucio.common.types import LoggerFunction
24
25
 
25
26
 
@@ -42,10 +43,10 @@ class DecommissioningProfile:
42
43
  """
43
44
 
44
45
  rse: dict[str, Any]
45
- initializer: Callable[..., None]
46
- discoverer: Callable[..., Iterable[dict[str, Any]]]
47
- handlers: list[tuple[Callable[..., bool], Callable[..., HandlerOutcome]]]
48
- finalizer: Callable[..., bool]
46
+ initializer: "Callable[..., None]"
47
+ discoverer: "Callable[..., Iterable[dict[str, Any]]]"
48
+ handlers: list[tuple["Callable[..., bool]", "Callable[..., HandlerOutcome]"]]
49
+ finalizer: "Callable[..., bool]"
49
50
 
50
51
  def initialize(
51
52
  self,
@@ -59,7 +60,7 @@ class DecommissioningProfile:
59
60
  self,
60
61
  *,
61
62
  logger: "LoggerFunction" = logging.log
62
- ) -> Iterable[dict[str, Any]]:
63
+ ) -> 'Iterable[dict[str, Any]]':
63
64
  """Call the discoverer."""
64
65
  return self.discoverer(self.rse, logger=logger)
65
66
 
@@ -98,7 +98,7 @@ def run_once(
98
98
  # Get the decommission attribute (encodes the decommissioning config)
99
99
  attr = get_rse_attribute(rse['id'], RseAttr.DECOMMISSION)
100
100
  try:
101
- config = attr_to_config(attr)
101
+ config = attr_to_config(attr) # type: ignore (attr could be None)
102
102
  except InvalidStatusName:
103
103
  logger(logging.ERROR, 'RSE %s has an invalid decommissioning status',
104
104
  rse['rse'])
@@ -35,7 +35,7 @@ from sqlalchemy.orm.exc import FlushError
35
35
 
36
36
  from rucio.common import exception
37
37
  from rucio.common.logging import formatted_logger, setup_logging
38
- from rucio.common.types import InternalAccount, InternalScope
38
+ from rucio.common.types import InternalAccount, InternalScope, LFNDict
39
39
  from rucio.common.utils import daemon_sleep
40
40
  from rucio.core.heartbeat import die, live, sanity_check
41
41
  from rucio.core.monitor import MetricManager
@@ -443,16 +443,18 @@ def process_dark_files(
443
443
  logger(logging.INFO, 'Processing a dark file:\n RSE %s Scope: %s Name: %s'
444
444
  % (rse, scope, name))
445
445
  rse_id = get_rse_id(rse=rse)
446
- Intscope = InternalScope(scope=scope, vo=issuer.vo)
447
- lfns = [{'scope': scope, 'name': name}]
448
-
446
+ internal_scope = InternalScope(scope=scope, vo=issuer.vo)
447
+ lfn: "LFNDict" = {
448
+ 'scope': scope,
449
+ 'name': name,
450
+ }
449
451
  attributes = get_rse_info(rse=rse)
450
- pfns = lfns2pfns(rse_settings=attributes, lfns=lfns, operation='delete')
452
+ pfns = lfns2pfns(rse_settings=attributes, lfns=[lfn], operation='delete')
451
453
  pfn_key = scope + ':' + name
452
454
  url = pfns[pfn_key]
453
455
  urls = [url]
454
456
  paths = parse_pfns(attributes, urls, operation='delete')
455
- replicas = [{'scope': Intscope, 'rse_id': rse_id, 'name': name,
457
+ replicas = [{'scope': internal_scope, 'rse_id': rse_id, 'name': name,
456
458
  'path': paths[url]['path'] + paths[url]['name']}]
457
459
  add_quarantined_replicas(rse_id, replicas, session=None)
458
460
  deleted_files += 1