rucio 37.0.0rc2__py3-none-any.whl → 37.0.0rc4__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 (67) hide show
  1. rucio/common/stomp_utils.py +119 -383
  2. rucio/daemons/cache/consumer.py +90 -26
  3. rucio/daemons/conveyor/receiver.py +123 -53
  4. rucio/daemons/hermes/hermes.py +344 -43
  5. rucio/daemons/tracer/kronos.py +139 -114
  6. rucio/vcsversion.py +3 -3
  7. {rucio-37.0.0rc2.dist-info → rucio-37.0.0rc4.dist-info}/METADATA +1 -1
  8. {rucio-37.0.0rc2.dist-info → rucio-37.0.0rc4.dist-info}/RECORD +67 -67
  9. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/alembic.ini.template +0 -0
  10. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
  11. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/globus-config.yml.template +0 -0
  12. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/ldap.cfg.template +0 -0
  13. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
  14. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
  15. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
  16. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
  17. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
  18. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
  19. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
  20. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
  21. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/rucio.cfg.template +0 -0
  22. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
  23. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/requirements.server.txt +0 -0
  24. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/tools/bootstrap.py +0 -0
  25. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
  26. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/data/rucio/tools/reset_database.py +0 -0
  27. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio +0 -0
  28. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-abacus-account +0 -0
  29. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-abacus-collection-replica +0 -0
  30. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-abacus-rse +0 -0
  31. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-admin +0 -0
  32. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-atropos +0 -0
  33. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-auditor +0 -0
  34. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-automatix +0 -0
  35. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-bb8 +0 -0
  36. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-cache-client +0 -0
  37. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-cache-consumer +0 -0
  38. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-finisher +0 -0
  39. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-poller +0 -0
  40. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-preparer +0 -0
  41. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-receiver +0 -0
  42. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-stager +0 -0
  43. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-submitter +0 -0
  44. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-throttler +0 -0
  45. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-dark-reaper +0 -0
  46. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-dumper +0 -0
  47. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-follower +0 -0
  48. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-hermes +0 -0
  49. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-judge-cleaner +0 -0
  50. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-judge-evaluator +0 -0
  51. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-judge-injector +0 -0
  52. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-judge-repairer +0 -0
  53. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-kronos +0 -0
  54. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-minos +0 -0
  55. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-minos-temporary-expiration +0 -0
  56. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-necromancer +0 -0
  57. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-oauth-manager +0 -0
  58. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-reaper +0 -0
  59. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-replica-recoverer +0 -0
  60. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-rse-decommissioner +0 -0
  61. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-storage-consistency-actions +0 -0
  62. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-transmogrifier +0 -0
  63. {rucio-37.0.0rc2.data → rucio-37.0.0rc4.data}/scripts/rucio-undertaker +0 -0
  64. {rucio-37.0.0rc2.dist-info → rucio-37.0.0rc4.dist-info}/WHEEL +0 -0
  65. {rucio-37.0.0rc2.dist-info → rucio-37.0.0rc4.dist-info}/licenses/AUTHORS.rst +0 -0
  66. {rucio-37.0.0rc2.dist-info → rucio-37.0.0rc4.dist-info}/licenses/LICENSE +0 -0
  67. {rucio-37.0.0rc2.dist-info → rucio-37.0.0rc4.dist-info}/top_level.txt +0 -0
@@ -21,8 +21,10 @@ import datetime
21
21
  import functools
22
22
  import json
23
23
  import logging
24
+ import random
24
25
  import re
25
26
  import smtplib
27
+ import socket
26
28
  import sys
27
29
  import threading
28
30
  import time
@@ -31,21 +33,28 @@ from email.mime.text import MIMEText
31
33
  from typing import TYPE_CHECKING, Any, Optional, Union
32
34
 
33
35
  import requests
36
+ import stomp
34
37
  from requests.auth import HTTPBasicAuth
35
38
 
36
39
  import rucio.db.sqla.util
37
- from rucio.common.config import config_get, config_get_bool, config_get_list
40
+ from rucio.common.config import (
41
+ config_get,
42
+ config_get_bool,
43
+ config_get_int,
44
+ config_get_list,
45
+ )
38
46
  from rucio.common.exception import DatabaseException
39
- from rucio.common.logging import formatted_logger, setup_logging
40
- from rucio.common.stomp_utils import ListenerBase, StompConnectionManager
47
+ from rucio.common.logging import setup_logging
41
48
  from rucio.core.message import delete_messages, retrieve_messages
42
49
  from rucio.core.monitor import MetricManager
43
50
  from rucio.daemons.common import run_daemon
44
51
 
45
52
  if TYPE_CHECKING:
46
- from collections.abc import Iterable
53
+ from collections.abc import Iterable, Sequence
47
54
  from types import FrameType
48
55
 
56
+ from stomp.utils import Frame
57
+
49
58
  from rucio.common.types import LoggerFunction
50
59
  from rucio.daemons.common import HeartbeatHandler
51
60
 
@@ -67,13 +76,264 @@ def default(datetype: Union[datetime.date, datetime.datetime]) -> str:
67
76
  return datetype.isoformat()
68
77
 
69
78
 
70
- class HermesListener(ListenerBase):
79
+ class HermesListener(stomp.ConnectionListener):
71
80
  """
72
81
  Hermes Listener
73
82
  """
74
83
 
84
+ def __init__(self, broker: str):
85
+ """
86
+ __init__
87
+ """
88
+ self.__broker = broker
89
+
90
+ def on_error(self, frame: "Frame") -> None:
91
+ """
92
+ Error handler
93
+ """
94
+ logging.error("[broker] [%s]: %s", self.__broker, frame.body)
95
+
96
+
97
+ def setup_activemq(
98
+ logger: "LoggerFunction"
99
+ ) -> tuple[
100
+ Optional[list[stomp.Connection12]],
101
+ Optional[str],
102
+ Optional[str],
103
+ Optional[str],
104
+ Optional[bool]
105
+ ]:
106
+ """
107
+ Deliver messages to ActiveMQ
108
+
109
+ :param logger: The logger object.
110
+ """
111
+
112
+ logger(logging.INFO, "[broker] Resolving brokers")
113
+
114
+ brokers_alias = []
115
+ brokers_resolved = []
116
+ try:
117
+ brokers_alias = config_get_list("messaging-hermes", "brokers")
118
+ except:
119
+ raise Exception("Could not load brokers from configuration")
120
+
121
+ logger(logging.INFO, "[broker] Resolving broker dns alias: %s", brokers_alias)
122
+ brokers_resolved = []
123
+ for broker in brokers_alias:
124
+ try:
125
+ addrinfos = socket.getaddrinfo(
126
+ broker, 0, socket.AF_INET, 0, socket.IPPROTO_TCP
127
+ )
128
+ brokers_resolved.extend(ai[4][0] for ai in addrinfos)
129
+ except socket.gaierror as ex:
130
+ logger(
131
+ logging.ERROR,
132
+ "[broker] Cannot resolve domain name %s (%s)",
133
+ broker,
134
+ str(ex),
135
+ )
136
+
137
+ logger(logging.DEBUG, "[broker] Brokers resolved to %s", brokers_resolved)
138
+
139
+ if not brokers_resolved:
140
+ logger(logging.FATAL, "[broker] No brokers resolved.")
141
+ return None, None, None, None, None
142
+
143
+ broker_timeout = 3
144
+ if not broker_timeout: # Allow zero in config
145
+ broker_timeout = None
146
+
147
+ logger(logging.INFO, "[broker] Checking authentication method")
148
+ use_ssl = True
149
+ try:
150
+ use_ssl = config_get_bool("messaging-hermes", "use_ssl")
151
+ except:
152
+ logger(
153
+ logging.INFO,
154
+ "[broker] Could not find use_ssl in configuration -- please update your rucio.cfg",
155
+ )
156
+
157
+ port = config_get_int("messaging-hermes", "port")
158
+ vhost = config_get("messaging-hermes", "broker_virtual_host", raise_exception=False)
159
+ username = None
160
+ password = None
161
+ if not use_ssl:
162
+ username = config_get("messaging-hermes", "username")
163
+ password = config_get("messaging-hermes", "password")
164
+ port = config_get_int("messaging-hermes", "nonssl_port")
165
+
166
+ conns = []
167
+ for broker in brokers_resolved:
168
+ if not use_ssl:
169
+ logger(
170
+ logging.INFO,
171
+ "[broker] setting up username/password authentication: %s",
172
+ broker,
173
+ )
174
+ else:
175
+ logger(
176
+ logging.INFO,
177
+ "[broker] setting up ssl cert/key authentication: %s",
178
+ broker,
179
+ )
180
+
181
+ con = stomp.Connection12(
182
+ host_and_ports=[(broker, port)],
183
+ vhost=vhost,
184
+ keepalive=True,
185
+ timeout=broker_timeout,
186
+ )
187
+ if use_ssl:
188
+ con.set_ssl(
189
+ key_file=config_get("messaging-hermes", "ssl_key_file"),
190
+ cert_file=config_get("messaging-hermes", "ssl_cert_file"),
191
+ )
192
+
193
+ con.set_listener(
194
+ "rucio-hermes", HermesListener(con.transport._Transport__host_and_ports[0])
195
+ )
196
+
197
+ conns.append(con)
198
+ destination = config_get("messaging-hermes", "destination")
199
+ return conns, destination, username, password, use_ssl
200
+
201
+
202
+ def deliver_to_activemq(
203
+ messages: "Iterable[dict[str, Any]]",
204
+ conns: "Sequence[stomp.Connection12]",
205
+ destination: str,
206
+ username: str,
207
+ password: str,
208
+ use_ssl: bool,
209
+ logger: "LoggerFunction"
210
+ ) -> list[str]:
211
+ """
212
+ Deliver messages to ActiveMQ
213
+
214
+ :param messages: The list of messages.
215
+ :param conns: A list of connections.
216
+ :param destination: The destination topic or queue.
217
+ :param username: The username if no SSL connection.
218
+ :param password: The username if no SSL connection.
219
+ :param use_ssl: Boolean to choose if SSL connection is used.
220
+ :param logger: The logger object.
221
+
222
+ :returns: List of message_id to delete
223
+ """
224
+ to_delete = []
225
+ for message in messages:
226
+ try:
227
+ conn = random.sample(conns, 1)[0]
228
+ if not conn.is_connected():
229
+ host_and_ports = conn.transport._Transport__host_and_ports[0][0]
230
+ RECONNECT_COUNTER.labels(host=host_and_ports.split(".")[0]).inc()
231
+ if not use_ssl:
232
+ logger(
233
+ logging.INFO,
234
+ "[broker] - connecting with USERPASS to %s",
235
+ host_and_ports,
236
+ )
237
+ conn.connect(username, password, wait=True)
238
+ else:
239
+ logger(
240
+ logging.INFO,
241
+ "[broker] - connecting with SSL to %s",
242
+ host_and_ports,
243
+ )
244
+ conn.connect(wait=True)
245
+
246
+ conn.send(
247
+ body=json.dumps(
248
+ {
249
+ "event_type": str(message["event_type"]).lower(),
250
+ "payload": message["payload"],
251
+ "created_at": str(message["created_at"]),
252
+ }
253
+ ),
254
+ destination=destination,
255
+ headers={
256
+ "persistent": "true",
257
+ "event_type": str(message["event_type"]).lower(),
258
+ },
259
+ )
260
+
261
+ to_delete.append(message["id"])
262
+ except ValueError:
263
+ logger(
264
+ logging.ERROR,
265
+ "[broker] Cannot serialize payload to JSON: %s",
266
+ str(message["payload"]),
267
+ )
268
+ to_delete.append(message["id"])
269
+ continue
270
+ except stomp.exception.NotConnectedException as error:
271
+ logger(
272
+ logging.WARNING,
273
+ "[broker] Could not deliver message due to NotConnectedException: %s",
274
+ str(error),
275
+ )
276
+ continue
277
+ except stomp.exception.ConnectFailedException as error:
278
+ logger(
279
+ logging.WARNING,
280
+ "[broker] Could not deliver message due to ConnectFailedException: %s",
281
+ str(error),
282
+ )
283
+ continue
284
+ except Exception as error:
285
+ logger(logging.ERROR, "[broker] Could not deliver message: %s", str(error))
286
+ continue
287
+
288
+ if str(message["event_type"]).lower().startswith("transfer") or str(
289
+ message["event_type"]
290
+ ).lower().startswith("stagein"):
291
+ logger(
292
+ logging.DEBUG,
293
+ "[broker] - event_type: %s, scope: %s, name: %s, rse: %s, request-id: %s, transfer-id: %s, created_at: %s",
294
+ str(message["event_type"]).lower(),
295
+ message["payload"].get("scope", None),
296
+ message["payload"].get("name", None),
297
+ message["payload"].get("dst-rse", None),
298
+ message["payload"].get("request-id", None),
299
+ message["payload"].get("transfer-id", None),
300
+ str(message["created_at"]),
301
+ )
302
+
303
+ elif str(message["event_type"]).lower().startswith("dataset"):
304
+ logger(
305
+ logging.DEBUG,
306
+ "[broker] - event_type: %s, scope: %s, name: %s, rse: %s, rule-id: %s, created_at: %s)",
307
+ str(message["event_type"]).lower(),
308
+ message["payload"].get("scope", None),
309
+ message["payload"].get("name", None),
310
+ message["payload"].get("rse", None),
311
+ message["payload"].get("rule_id", None),
312
+ str(message["created_at"]),
313
+ )
314
+
315
+ elif str(message["event_type"]).lower().startswith("deletion"):
316
+ if "url" not in message["payload"]:
317
+ message["payload"]["url"] = "unknown"
318
+ logger(
319
+ logging.DEBUG,
320
+ "[broker] - event_type: %s, scope: %s, name: %s, rse: %s, url: %s, created_at: %s)",
321
+ str(message["event_type"]).lower(),
322
+ message["payload"].get("scope", None),
323
+ message["payload"].get("name", None),
324
+ message["payload"].get("rse", None),
325
+ message["payload"].get("url", None),
326
+ str(message["created_at"]),
327
+ )
328
+ else:
329
+ logger(logging.DEBUG, "[broker] Other message: %s", message)
330
+ return to_delete
331
+
75
332
 
76
- def deliver_emails(messages: "Iterable[dict[str, Any]]", logger: "LoggerFunction") -> list[int]:
333
+ def deliver_emails(
334
+ messages: "Iterable[dict[str, Any]]",
335
+ logger: "LoggerFunction"
336
+ ) -> list[str]:
77
337
  """
78
338
  Sends emails
79
339
 
@@ -137,10 +397,9 @@ def submit_to_elastic(
137
397
 
138
398
  for message in messages:
139
399
  text += '{ "index":{ } }\n%s\n' % json.dumps(message, default=default)
140
- res = requests.post(endpoint,
141
- data=text,
142
- headers={"Content-Type": "application/json"},
143
- auth=auth)
400
+ res = requests.post(
401
+ endpoint, data=text, headers={"Content-Type": "application/json"}, auth=auth
402
+ )
144
403
  return res.status_code
145
404
 
146
405
 
@@ -170,9 +429,11 @@ def aggregate_to_influx(
170
429
  payload = message["payload"]
171
430
  if event_type in ["transfer-failed", "transfer-done"]:
172
431
  if not payload["transferred_at"]:
173
- logger(logging.WARNING,
174
- "No transferred_at for message. Reason : %s",
175
- payload["reason"])
432
+ logger(
433
+ logging.WARNING,
434
+ "No transferred_at for message. Reason : %s",
435
+ payload["reason"],
436
+ )
176
437
  continue
177
438
  transferred_at = time.strptime(
178
439
  payload["transferred_at"], "%Y-%m-%d %H:%M:%S"
@@ -188,7 +449,11 @@ def aggregate_to_influx(
188
449
  payload["activity"],
189
450
  )
190
451
  activity = re.sub(" ", r"\ ", activity)
191
- key = f"transfer,activity={activity!s},src_rse={src_rse!s},dst_rse={dest_rse!s}"
452
+ key = "transfer,activity=%s,src_rse=%s,dst_rse=%s" % (
453
+ activity,
454
+ src_rse,
455
+ dest_rse,
456
+ )
192
457
  if key not in bins[transferred_at]:
193
458
  bins[transferred_at][key] = [0, 0, 0, 0]
194
459
  if event_type == "transfer-done":
@@ -208,7 +473,7 @@ def aggregate_to_influx(
208
473
  if created_at not in bins:
209
474
  bins[created_at] = {}
210
475
  rse = payload["rse"]
211
- key = f"deletion,rse={rse!s}"
476
+ key = "deletion,rse=%s" % (rse)
212
477
  if key not in bins[created_at]:
213
478
  bins[created_at][key] = [0, 0, 0, 0]
214
479
  if event_type == "deletion-done":
@@ -217,22 +482,31 @@ def aggregate_to_influx(
217
482
  if event_type == "deletion-failed":
218
483
  bins[created_at][key][2] += 1
219
484
  bins[created_at][key][3] += payload["bytes"]
220
-
221
485
  points = ""
222
- for timestamp, entries in bins.items():
223
- for key, metrics in entries.items():
224
- event_type = key.split(",")[0]
225
- points += (f"{key!s} "
226
- f"nb_{event_type!s}_done={metrics[0]!s},"
227
- f"bytes_{event_type!s}_done={metrics[1]!s},"
228
- f"nb_{event_type!s}_failed={metrics[2]!s},"
229
- f"bytes_{event_type!s}_failed={metrics[3]!s} "
230
- rf"{timestamp!s}\n")
231
-
486
+ for timestamp in bins:
487
+ for entry in bins[timestamp]:
488
+ metrics = bins[timestamp][entry]
489
+ event_type = entry.split(",")[0]
490
+ point = (
491
+ "%s nb_%s_done=%s,bytes_%s_done=%s,nb_%s_failed=%s,bytes_%s_failed=%s %s"
492
+ % (
493
+ entry,
494
+ event_type,
495
+ metrics[0],
496
+ event_type,
497
+ metrics[1],
498
+ event_type,
499
+ metrics[2],
500
+ event_type,
501
+ metrics[3],
502
+ timestamp,
503
+ )
504
+ )
505
+ points += point
506
+ points += "\n"
232
507
  influx_token = config_get("hermes", "influxdb_token", False, None)
233
- headers = {}
234
508
  if influx_token:
235
- headers["Authorization"] = f"Token {influx_token!s}"
509
+ headers = {"Authorization": "Token %s" % influx_token}
236
510
  if points:
237
511
  res = requests.post(endpoint, headers=headers, data=points)
238
512
  logger(logging.DEBUG, "%s", str(res.text))
@@ -357,10 +631,16 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
357
631
  )
358
632
  except Exception as err:
359
633
  logger(logging.ERROR, str(err))
360
- conns = None
361
634
  if "activemq" in services_list:
362
- conn_mgr = StompConnectionManager(config_section='messaging-hermes', logger=logger)
363
- conn_mgr.set_listener_factory("rucio-hermes", HermesListener, heartbeats=conn_mgr.config.heartbeats)
635
+ try:
636
+ conns, destination, username, password, use_ssl = setup_activemq(logger)
637
+ if not conns:
638
+ logger(
639
+ logging.ERROR,
640
+ "ActiveMQ defined in the services list, cannot be setup",
641
+ )
642
+ except Exception as err:
643
+ logger(logging.ERROR, str(err))
364
644
 
365
645
  worker_number, total_workers, logger = heartbeat_handler.live()
366
646
  message_dict = {}
@@ -465,10 +745,18 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
465
745
  except Exception as error:
466
746
  logger(logging.ERROR, "Error sending email : %s", str(error))
467
747
 
468
- if "activemq" in message_dict and conns:
748
+ if "activemq" in message_dict:
469
749
  t_time = time.time()
470
750
  try:
471
- messages_sent = conn_mgr.deliver_messages(messages=message_dict["activemq"])
751
+ messages_sent = deliver_to_activemq(
752
+ messages=message_dict["activemq"],
753
+ conns=conns, # type: ignore (argument could be None)
754
+ destination=destination, # type: ignore (argument could be None)
755
+ username=username, # type: ignore (argument could be None)
756
+ password=password, # type: ignore (argument could be None)
757
+ use_ssl=use_ssl, # type: ignore (argument could be None)
758
+ logger=logger,
759
+ )
472
760
  logger(
473
761
  logging.INFO,
474
762
  "%s messages successfully submitted to ActiveMQ in %s seconds",
@@ -517,18 +805,31 @@ def run(
517
805
  Starts up the hermes threads.
518
806
  """
519
807
  setup_logging(process_name=DAEMON_NAME)
520
- logger = formatted_logger(logging.log, DAEMON_NAME + ' %s')
521
808
 
522
809
  if rucio.db.sqla.util.is_old_db():
523
810
  raise DatabaseException("Database was not updated, daemon won't start")
524
811
 
525
- logger(logging.INFO, "starting hermes threads")
526
- thread_list = []
527
- for _ in range(threads):
528
- her_thread = threading.Thread(target=hermes, kwargs={"once": once, "bulk": bulk, "sleep_time": sleep_time})
529
- her_thread.start()
530
- thread_list.append(her_thread)
812
+ logging.info("starting hermes threads")
813
+ thread_list = [
814
+ threading.Thread(
815
+ target=hermes,
816
+ kwargs={
817
+ "once": once,
818
+ "bulk": bulk,
819
+ "sleep_time": sleep_time,
820
+ },
821
+ )
822
+ for _ in range(0, threads)
823
+ ]
531
824
 
532
- logger(logging.DEBUG, thread_list)
533
- while [thread.join(timeout=3.14) for thread in thread_list if thread.is_alive()]:
534
- pass
825
+ for thrd in thread_list:
826
+ thrd.start()
827
+
828
+ logging.debug(thread_list)
829
+ # Interruptible joins require a timeout.
830
+ while thread_list:
831
+ thread_list = [
832
+ thread.join(timeout=3.14)
833
+ for thread in thread_list
834
+ if thread and thread.is_alive()
835
+ ]