rucio 37.0.0rc3__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.
- rucio/common/stomp_utils.py +119 -383
- rucio/daemons/cache/consumer.py +90 -26
- rucio/daemons/conveyor/receiver.py +123 -53
- rucio/daemons/hermes/hermes.py +343 -41
- rucio/daemons/tracer/kronos.py +139 -114
- rucio/vcsversion.py +3 -3
- {rucio-37.0.0rc3.dist-info → rucio-37.0.0rc4.dist-info}/METADATA +1 -1
- {rucio-37.0.0rc3.dist-info → rucio-37.0.0rc4.dist-info}/RECORD +67 -67
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/alembic.ini.template +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/ldap.cfg.template +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/rucio.cfg.template +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/requirements.server.txt +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/tools/bootstrap.py +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/data/rucio/tools/reset_database.py +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-abacus-account +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-abacus-collection-replica +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-abacus-rse +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-admin +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-atropos +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-auditor +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-automatix +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-bb8 +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-cache-client +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-cache-consumer +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-finisher +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-poller +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-preparer +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-receiver +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-stager +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-submitter +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-conveyor-throttler +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-dark-reaper +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-dumper +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-follower +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-hermes +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-judge-cleaner +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-judge-evaluator +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-judge-injector +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-judge-repairer +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-kronos +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-minos +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-minos-temporary-expiration +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-necromancer +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-oauth-manager +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-reaper +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-replica-recoverer +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-rse-decommissioner +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-storage-consistency-actions +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-transmogrifier +0 -0
- {rucio-37.0.0rc3.data → rucio-37.0.0rc4.data}/scripts/rucio-undertaker +0 -0
- {rucio-37.0.0rc3.dist-info → rucio-37.0.0rc4.dist-info}/WHEEL +0 -0
- {rucio-37.0.0rc3.dist-info → rucio-37.0.0rc4.dist-info}/licenses/AUTHORS.rst +0 -0
- {rucio-37.0.0rc3.dist-info → rucio-37.0.0rc4.dist-info}/licenses/LICENSE +0 -0
- {rucio-37.0.0rc3.dist-info → rucio-37.0.0rc4.dist-info}/top_level.txt +0 -0
rucio/daemons/hermes/hermes.py
CHANGED
|
@@ -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
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
141
|
-
|
|
142
|
-
|
|
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(
|
|
174
|
-
|
|
175
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
223
|
-
for
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
|
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))
|
|
@@ -358,8 +632,15 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
358
632
|
except Exception as err:
|
|
359
633
|
logger(logging.ERROR, str(err))
|
|
360
634
|
if "activemq" in services_list:
|
|
361
|
-
|
|
362
|
-
|
|
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))
|
|
363
644
|
|
|
364
645
|
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
365
646
|
message_dict = {}
|
|
@@ -467,7 +748,15 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
467
748
|
if "activemq" in message_dict:
|
|
468
749
|
t_time = time.time()
|
|
469
750
|
try:
|
|
470
|
-
messages_sent =
|
|
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
|
+
)
|
|
471
760
|
logger(
|
|
472
761
|
logging.INFO,
|
|
473
762
|
"%s messages successfully submitted to ActiveMQ in %s seconds",
|
|
@@ -516,18 +805,31 @@ def run(
|
|
|
516
805
|
Starts up the hermes threads.
|
|
517
806
|
"""
|
|
518
807
|
setup_logging(process_name=DAEMON_NAME)
|
|
519
|
-
logger = formatted_logger(logging.log, DAEMON_NAME + ' %s')
|
|
520
808
|
|
|
521
809
|
if rucio.db.sqla.util.is_old_db():
|
|
522
810
|
raise DatabaseException("Database was not updated, daemon won't start")
|
|
523
811
|
|
|
524
|
-
|
|
525
|
-
thread_list = [
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
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
|
+
]
|
|
530
824
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
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
|
+
]
|