rucio-clients 32.8.6__py3-none-any.whl → 35.8.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-clients might be problematic. Click here for more details.
- rucio/__init__.py +0 -1
- rucio/alembicrevision.py +1 -2
- rucio/client/__init__.py +0 -1
- rucio/client/accountclient.py +45 -25
- rucio/client/accountlimitclient.py +37 -9
- rucio/client/baseclient.py +199 -154
- rucio/client/client.py +2 -3
- rucio/client/configclient.py +19 -6
- rucio/client/credentialclient.py +9 -4
- rucio/client/didclient.py +238 -63
- rucio/client/diracclient.py +13 -5
- rucio/client/downloadclient.py +162 -51
- rucio/client/exportclient.py +4 -4
- rucio/client/fileclient.py +3 -4
- rucio/client/importclient.py +4 -4
- rucio/client/lifetimeclient.py +21 -5
- rucio/client/lockclient.py +18 -8
- rucio/client/{metaclient.py → metaconventionsclient.py} +18 -15
- rucio/client/pingclient.py +0 -1
- rucio/client/replicaclient.py +15 -5
- rucio/client/requestclient.py +35 -19
- rucio/client/rseclient.py +133 -51
- rucio/client/ruleclient.py +29 -22
- rucio/client/scopeclient.py +8 -6
- rucio/client/subscriptionclient.py +47 -35
- rucio/client/touchclient.py +8 -4
- rucio/client/uploadclient.py +166 -82
- rucio/common/__init__.py +0 -1
- rucio/common/cache.py +4 -4
- rucio/common/config.py +52 -47
- rucio/common/constants.py +69 -2
- rucio/common/constraints.py +0 -1
- rucio/common/didtype.py +24 -22
- rucio/common/exception.py +281 -222
- rucio/common/extra.py +0 -1
- rucio/common/logging.py +54 -38
- rucio/common/pcache.py +122 -101
- rucio/common/plugins.py +153 -0
- rucio/common/policy.py +4 -4
- rucio/common/schema/__init__.py +17 -10
- rucio/common/schema/atlas.py +7 -5
- rucio/common/schema/belleii.py +7 -5
- rucio/common/schema/domatpc.py +7 -5
- rucio/common/schema/escape.py +7 -5
- rucio/common/schema/generic.py +8 -6
- rucio/common/schema/generic_multi_vo.py +7 -5
- rucio/common/schema/icecube.py +7 -5
- rucio/common/stomp_utils.py +0 -1
- rucio/common/stopwatch.py +0 -1
- rucio/common/test_rucio_server.py +2 -2
- rucio/common/types.py +262 -17
- rucio/common/utils.py +743 -451
- rucio/rse/__init__.py +3 -4
- rucio/rse/protocols/__init__.py +0 -1
- rucio/rse/protocols/bittorrent.py +184 -0
- rucio/rse/protocols/cache.py +1 -2
- rucio/rse/protocols/dummy.py +1 -2
- rucio/rse/protocols/gfal.py +12 -10
- rucio/rse/protocols/globus.py +7 -7
- rucio/rse/protocols/gsiftp.py +2 -3
- rucio/rse/protocols/http_cache.py +1 -2
- rucio/rse/protocols/mock.py +1 -2
- rucio/rse/protocols/ngarc.py +1 -2
- rucio/rse/protocols/posix.py +12 -13
- rucio/rse/protocols/protocol.py +116 -52
- rucio/rse/protocols/rclone.py +6 -7
- rucio/rse/protocols/rfio.py +4 -5
- rucio/rse/protocols/srm.py +9 -10
- rucio/rse/protocols/ssh.py +8 -9
- rucio/rse/protocols/storm.py +2 -3
- rucio/rse/protocols/webdav.py +17 -14
- rucio/rse/protocols/xrootd.py +23 -17
- rucio/rse/rsemanager.py +19 -7
- rucio/vcsversion.py +4 -4
- rucio/version.py +5 -13
- rucio_clients-35.8.0.data/data/requirements.client.txt +15 -0
- {rucio_clients-32.8.6.data → rucio_clients-35.8.0.data}/data/rucio_client/merge_rucio_configs.py +2 -5
- {rucio_clients-32.8.6.data → rucio_clients-35.8.0.data}/scripts/rucio +87 -85
- {rucio_clients-32.8.6.data → rucio_clients-35.8.0.data}/scripts/rucio-admin +45 -32
- {rucio_clients-32.8.6.dist-info → rucio_clients-35.8.0.dist-info}/METADATA +13 -13
- rucio_clients-35.8.0.dist-info/RECORD +88 -0
- {rucio_clients-32.8.6.dist-info → rucio_clients-35.8.0.dist-info}/WHEEL +1 -1
- {rucio_clients-32.8.6.dist-info → rucio_clients-35.8.0.dist-info}/licenses/AUTHORS.rst +3 -0
- rucio/common/schema/cms.py +0 -478
- rucio/common/schema/lsst.py +0 -423
- rucio_clients-32.8.6.data/data/requirements.txt +0 -55
- rucio_clients-32.8.6.dist-info/RECORD +0 -88
- {rucio_clients-32.8.6.data → rucio_clients-35.8.0.data}/data/etc/rse-accounts.cfg.template +0 -0
- {rucio_clients-32.8.6.data → rucio_clients-35.8.0.data}/data/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio_clients-32.8.6.data → rucio_clients-35.8.0.data}/data/etc/rucio.cfg.template +0 -0
- {rucio_clients-32.8.6.dist-info → rucio_clients-35.8.0.dist-info}/licenses/LICENSE +0 -0
- {rucio_clients-32.8.6.dist-info → rucio_clients-35.8.0.dist-info}/top_level.txt +0 -0
rucio/client/rseclient.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -14,21 +13,26 @@
|
|
|
14
13
|
# limitations under the License.
|
|
15
14
|
|
|
16
15
|
from json import dumps, loads
|
|
16
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, Union
|
|
17
17
|
from urllib.parse import quote
|
|
18
18
|
|
|
19
19
|
from requests.status_codes import codes
|
|
20
20
|
|
|
21
|
-
from rucio.client.baseclient import BaseClient
|
|
22
|
-
from rucio.client.baseclient import choice
|
|
21
|
+
from rucio.client.baseclient import BaseClient, choice
|
|
23
22
|
from rucio.common.utils import build_url
|
|
24
23
|
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from collections.abc import Iterable, Iterator
|
|
26
|
+
|
|
27
|
+
from rucio.common.constants import RSE_SUPPORTED_PROTOCOL_DOMAINS_LITERAL, RSE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL, SUPPORTED_PROTOCOLS_LITERAL
|
|
28
|
+
|
|
25
29
|
|
|
26
30
|
class RSEClient(BaseClient):
|
|
27
31
|
"""RSE client class for working with rucio RSEs"""
|
|
28
32
|
|
|
29
33
|
RSE_BASEURL = 'rses'
|
|
30
34
|
|
|
31
|
-
def get_rse(self, rse):
|
|
35
|
+
def get_rse(self, rse: str) -> dict[str, Any]:
|
|
32
36
|
"""
|
|
33
37
|
Returns details about the referred RSE.
|
|
34
38
|
|
|
@@ -43,13 +47,13 @@ class RSEClient(BaseClient):
|
|
|
43
47
|
|
|
44
48
|
r = self._send_request(url, type_='GET')
|
|
45
49
|
if r.status_code == codes.ok:
|
|
46
|
-
|
|
47
|
-
return
|
|
50
|
+
rse_dict = loads(r.text)
|
|
51
|
+
return rse_dict
|
|
48
52
|
else:
|
|
49
53
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
50
54
|
raise exc_cls(exc_msg)
|
|
51
55
|
|
|
52
|
-
def add_rse(self, rse, **kwargs):
|
|
56
|
+
def add_rse(self, rse: str, **kwargs) -> Literal[True]:
|
|
53
57
|
"""
|
|
54
58
|
Sends the request to create a new RSE.
|
|
55
59
|
|
|
@@ -80,12 +84,12 @@ class RSEClient(BaseClient):
|
|
|
80
84
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
81
85
|
raise exc_cls(exc_msg)
|
|
82
86
|
|
|
83
|
-
def update_rse(self, rse, parameters):
|
|
87
|
+
def update_rse(self, rse: str, parameters: dict[str, Any]) -> Literal[True]:
|
|
84
88
|
"""
|
|
85
89
|
Update RSE properties like availability or name.
|
|
86
90
|
|
|
87
91
|
:param rse: the name of the new rse.
|
|
88
|
-
:param parameters: A
|
|
92
|
+
:param parameters: A dictionary with property (name, read, write, delete as keys).
|
|
89
93
|
"""
|
|
90
94
|
path = 'rses/' + rse
|
|
91
95
|
url = build_url(choice(self.list_hosts), path=path)
|
|
@@ -95,7 +99,7 @@ class RSEClient(BaseClient):
|
|
|
95
99
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
96
100
|
raise exc_cls(exc_msg)
|
|
97
101
|
|
|
98
|
-
def delete_rse(self, rse):
|
|
102
|
+
def delete_rse(self, rse: str) -> Literal[True]:
|
|
99
103
|
"""
|
|
100
104
|
Sends the request to delete a rse.
|
|
101
105
|
|
|
@@ -111,7 +115,7 @@ class RSEClient(BaseClient):
|
|
|
111
115
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
112
116
|
raise exc_cls(exc_msg)
|
|
113
117
|
|
|
114
|
-
def list_rses(self, rse_expression=None):
|
|
118
|
+
def list_rses(self, rse_expression: Optional[str] = None) -> "Iterator[dict[str, Any]]":
|
|
115
119
|
"""
|
|
116
120
|
Sends the request to list all rucio locations(RSEs).
|
|
117
121
|
|
|
@@ -131,7 +135,12 @@ class RSEClient(BaseClient):
|
|
|
131
135
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
132
136
|
raise exc_cls(exc_msg)
|
|
133
137
|
|
|
134
|
-
def add_rse_attribute(
|
|
138
|
+
def add_rse_attribute(
|
|
139
|
+
self,
|
|
140
|
+
rse: str,
|
|
141
|
+
key: str,
|
|
142
|
+
value: Any
|
|
143
|
+
) -> Literal[True]:
|
|
135
144
|
"""
|
|
136
145
|
Sends the request to add a RSE attribute.
|
|
137
146
|
|
|
@@ -153,7 +162,7 @@ class RSEClient(BaseClient):
|
|
|
153
162
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
154
163
|
raise exc_cls(exc_msg)
|
|
155
164
|
|
|
156
|
-
def delete_rse_attribute(self, rse, key):
|
|
165
|
+
def delete_rse_attribute(self, rse: str, key: str) -> Literal[True]:
|
|
157
166
|
"""
|
|
158
167
|
Sends the request to delete a RSE attribute.
|
|
159
168
|
|
|
@@ -172,7 +181,7 @@ class RSEClient(BaseClient):
|
|
|
172
181
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
173
182
|
raise exc_cls(exc_msg)
|
|
174
183
|
|
|
175
|
-
def list_rse_attributes(self, rse):
|
|
184
|
+
def list_rse_attributes(self, rse: str) -> dict[str, Any]:
|
|
176
185
|
"""
|
|
177
186
|
Sends the request to get RSE attributes.
|
|
178
187
|
|
|
@@ -190,7 +199,7 @@ class RSEClient(BaseClient):
|
|
|
190
199
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
191
200
|
raise exc_cls(exc_msg)
|
|
192
201
|
|
|
193
|
-
def add_protocol(self, rse, params):
|
|
202
|
+
def add_protocol(self, rse: str, params: dict[str, Any]) -> Literal[True]:
|
|
194
203
|
"""
|
|
195
204
|
Sends the request to create a new protocol for the given RSE.
|
|
196
205
|
|
|
@@ -225,9 +234,16 @@ class RSEClient(BaseClient):
|
|
|
225
234
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
226
235
|
raise exc_cls(exc_msg)
|
|
227
236
|
|
|
228
|
-
def get_protocols(
|
|
237
|
+
def get_protocols(
|
|
238
|
+
self,
|
|
239
|
+
rse: str,
|
|
240
|
+
protocol_domain: "RSE_SUPPORTED_PROTOCOL_DOMAINS_LITERAL" = 'ALL',
|
|
241
|
+
operation: Optional["RSE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL"] = None,
|
|
242
|
+
default: bool = False,
|
|
243
|
+
scheme: Optional['SUPPORTED_PROTOCOLS_LITERAL'] = None
|
|
244
|
+
) -> Any:
|
|
229
245
|
"""
|
|
230
|
-
Returns protocol information. Parameter
|
|
246
|
+
Returns protocol information. Parameter combinations are:
|
|
231
247
|
(operation OR default) XOR protocol.
|
|
232
248
|
|
|
233
249
|
:param rse: the RSE name.
|
|
@@ -237,7 +253,7 @@ class RSEClient(BaseClient):
|
|
|
237
253
|
:param default: Indicates if only the default operations should be returned.
|
|
238
254
|
:param scheme: The identifier of the requested protocol.
|
|
239
255
|
|
|
240
|
-
:returns: A
|
|
256
|
+
:returns: A dict with details about each matching protocol.
|
|
241
257
|
|
|
242
258
|
:raises RSENotFound: if the RSE doesn't exist.
|
|
243
259
|
:raises RSEProtocolNotSupported: if no matching protocol entry could be found.
|
|
@@ -266,7 +282,14 @@ class RSEClient(BaseClient):
|
|
|
266
282
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
267
283
|
raise exc_cls(exc_msg)
|
|
268
284
|
|
|
269
|
-
def lfns2pfns(
|
|
285
|
+
def lfns2pfns(
|
|
286
|
+
self,
|
|
287
|
+
rse: str,
|
|
288
|
+
lfns: 'Iterable[str]',
|
|
289
|
+
protocol_domain: 'RSE_SUPPORTED_PROTOCOL_DOMAINS_LITERAL' = 'ALL',
|
|
290
|
+
operation: Optional['RSE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL'] = None,
|
|
291
|
+
scheme: Optional['SUPPORTED_PROTOCOLS_LITERAL'] = None
|
|
292
|
+
) -> dict[str, str]:
|
|
270
293
|
"""
|
|
271
294
|
Returns PFNs that should be used at a RSE, corresponding to requested LFNs.
|
|
272
295
|
The PFNs are generated for the RSE *regardless* of whether a replica exists for the LFN.
|
|
@@ -305,7 +328,13 @@ class RSEClient(BaseClient):
|
|
|
305
328
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
306
329
|
raise exc_cls(exc_msg)
|
|
307
330
|
|
|
308
|
-
def delete_protocols(
|
|
331
|
+
def delete_protocols(
|
|
332
|
+
self,
|
|
333
|
+
rse: str,
|
|
334
|
+
scheme: 'SUPPORTED_PROTOCOLS_LITERAL',
|
|
335
|
+
hostname: Optional[str] = None,
|
|
336
|
+
port: Optional[int] = None
|
|
337
|
+
) -> Literal[True]:
|
|
309
338
|
"""
|
|
310
339
|
Deletes matching protocols from RSE. Protocols using the same identifier can be
|
|
311
340
|
distinguished by hostname and port.
|
|
@@ -336,14 +365,20 @@ class RSEClient(BaseClient):
|
|
|
336
365
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
337
366
|
raise exc_cls(exc_msg)
|
|
338
367
|
|
|
339
|
-
def update_protocols(
|
|
368
|
+
def update_protocols(
|
|
369
|
+
self,
|
|
370
|
+
rse: str,
|
|
371
|
+
scheme: 'SUPPORTED_PROTOCOLS_LITERAL',
|
|
372
|
+
data: dict[str, Any],
|
|
373
|
+
hostname: Optional[str] = None,
|
|
374
|
+
port: Optional[int] = None):
|
|
340
375
|
"""
|
|
341
376
|
Updates matching protocols from RSE. Protocol using the same identifier can be
|
|
342
377
|
distinguished by hostname and port.
|
|
343
378
|
|
|
344
379
|
:param rse: the RSE name.
|
|
345
380
|
:param scheme: identifier of the protocol.
|
|
346
|
-
:param data: A dict providing the new values of the protocol
|
|
381
|
+
:param data: A dict providing the new values of the protocol attributes.
|
|
347
382
|
Keys must match column names in database.
|
|
348
383
|
:param hostname: hostname of the protocol.
|
|
349
384
|
:param port: port of the protocol.
|
|
@@ -370,7 +405,14 @@ class RSEClient(BaseClient):
|
|
|
370
405
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
371
406
|
raise exc_cls(exc_msg)
|
|
372
407
|
|
|
373
|
-
def swap_protocols(
|
|
408
|
+
def swap_protocols(
|
|
409
|
+
self,
|
|
410
|
+
rse: str,
|
|
411
|
+
domain: 'RSE_SUPPORTED_PROTOCOL_DOMAINS_LITERAL',
|
|
412
|
+
operation: 'RSE_SUPPORTED_PROTOCOL_OPERATIONS_LITERAL',
|
|
413
|
+
scheme_a: 'SUPPORTED_PROTOCOLS_LITERAL',
|
|
414
|
+
scheme_b: 'SUPPORTED_PROTOCOLS_LITERAL'
|
|
415
|
+
) -> bool:
|
|
374
416
|
"""
|
|
375
417
|
Swaps the priorities of the provided operation.
|
|
376
418
|
|
|
@@ -387,22 +429,21 @@ class RSEClient(BaseClient):
|
|
|
387
429
|
:raises KeyNotFound: if invalid data was provided for update.
|
|
388
430
|
:raises AccessDenied: if not authorized.
|
|
389
431
|
"""
|
|
390
|
-
|
|
432
|
+
|
|
391
433
|
protocols = self.get_protocols(rse, domain, operation, False, scheme_a)['protocols']
|
|
392
|
-
for p in protocols
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
protocol_b = p
|
|
397
|
-
if (protocol_a or protocol_b) is None:
|
|
434
|
+
protocol_a = next((p for p in protocols if p['scheme'] == scheme_a), None)
|
|
435
|
+
protocol_b = next((p for p in protocols if p['scheme'] == scheme_b), None)
|
|
436
|
+
|
|
437
|
+
if protocol_a is None or protocol_b is None:
|
|
398
438
|
return False
|
|
439
|
+
|
|
399
440
|
priority_a = protocol_a['domains'][domain][operation]
|
|
400
441
|
priority_b = protocol_b['domains'][domain][operation]
|
|
401
442
|
self.update_protocols(rse, protocol_a['scheme'], {'domains': {domain: {operation: priority_b}}}, protocol_a['hostname'], protocol_a['port'])
|
|
402
443
|
self.update_protocols(rse, protocol_b['scheme'], {'domains': {domain: {operation: priority_a}}}, protocol_b['hostname'], protocol_b['port'])
|
|
403
444
|
return True
|
|
404
445
|
|
|
405
|
-
def add_qos_policy(self, rse, qos_policy):
|
|
446
|
+
def add_qos_policy(self, rse: str, qos_policy: str) -> Literal[True]:
|
|
406
447
|
"""
|
|
407
448
|
Add a QoS policy from an RSE.
|
|
408
449
|
|
|
@@ -424,7 +465,7 @@ class RSEClient(BaseClient):
|
|
|
424
465
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
425
466
|
raise exc_cls(exc_msg)
|
|
426
467
|
|
|
427
|
-
def delete_qos_policy(self, rse, qos_policy):
|
|
468
|
+
def delete_qos_policy(self, rse: str, qos_policy: str) -> Literal[True]:
|
|
428
469
|
"""
|
|
429
470
|
Delete a QoS policy from an RSE.
|
|
430
471
|
|
|
@@ -445,7 +486,7 @@ class RSEClient(BaseClient):
|
|
|
445
486
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
446
487
|
raise exc_cls(exc_msg)
|
|
447
488
|
|
|
448
|
-
def list_qos_policies(self, rse):
|
|
489
|
+
def list_qos_policies(self, rse: str) -> list[str]:
|
|
449
490
|
"""
|
|
450
491
|
List all QoS policies of an RSE.
|
|
451
492
|
|
|
@@ -465,7 +506,14 @@ class RSEClient(BaseClient):
|
|
|
465
506
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
466
507
|
raise exc_cls(exc_msg)
|
|
467
508
|
|
|
468
|
-
def set_rse_usage(
|
|
509
|
+
def set_rse_usage(
|
|
510
|
+
self,
|
|
511
|
+
rse: str,
|
|
512
|
+
source: str,
|
|
513
|
+
used: int,
|
|
514
|
+
free: int,
|
|
515
|
+
files: Optional[int] = None
|
|
516
|
+
) -> Literal[True]:
|
|
469
517
|
"""
|
|
470
518
|
Set RSE usage information.
|
|
471
519
|
|
|
@@ -475,7 +523,7 @@ class RSEClient(BaseClient):
|
|
|
475
523
|
:param free: the free in bytes.
|
|
476
524
|
:param files: the number of files
|
|
477
525
|
|
|
478
|
-
:returns: True if successful
|
|
526
|
+
:returns: True if successful
|
|
479
527
|
"""
|
|
480
528
|
path = [self.RSE_BASEURL, rse, 'usage']
|
|
481
529
|
path = '/'.join(path)
|
|
@@ -488,7 +536,11 @@ class RSEClient(BaseClient):
|
|
|
488
536
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
489
537
|
raise exc_cls(exc_msg)
|
|
490
538
|
|
|
491
|
-
def get_rse_usage(
|
|
539
|
+
def get_rse_usage(
|
|
540
|
+
self,
|
|
541
|
+
rse: str,
|
|
542
|
+
filters: Optional[dict[str, Any]] = None
|
|
543
|
+
) -> "Iterator[dict[str, Any]]":
|
|
492
544
|
"""
|
|
493
545
|
Get RSE usage information.
|
|
494
546
|
|
|
@@ -507,14 +559,18 @@ class RSEClient(BaseClient):
|
|
|
507
559
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
508
560
|
raise exc_cls(exc_msg)
|
|
509
561
|
|
|
510
|
-
def list_rse_usage_history(
|
|
562
|
+
def list_rse_usage_history(
|
|
563
|
+
self,
|
|
564
|
+
rse: str,
|
|
565
|
+
filters: Optional[dict[str, Any]] = None
|
|
566
|
+
) -> "Iterator[dict[str, Any]]":
|
|
511
567
|
"""
|
|
512
568
|
List RSE usage history information.
|
|
513
569
|
|
|
514
570
|
:param rse: The RSE name.
|
|
515
571
|
:param filters: dictionary of attributes by which the results should be filtered.
|
|
516
572
|
|
|
517
|
-
:returns: list of
|
|
573
|
+
:returns: list of dictionaries.
|
|
518
574
|
"""
|
|
519
575
|
path = [self.RSE_BASEURL, rse, 'usage', 'history']
|
|
520
576
|
path = '/'.join(path)
|
|
@@ -528,7 +584,12 @@ class RSEClient(BaseClient):
|
|
|
528
584
|
data=r.content)
|
|
529
585
|
raise exc_cls(exc_msg)
|
|
530
586
|
|
|
531
|
-
def set_rse_limits(
|
|
587
|
+
def set_rse_limits(
|
|
588
|
+
self,
|
|
589
|
+
rse: str,
|
|
590
|
+
name: str,
|
|
591
|
+
value: int
|
|
592
|
+
) -> Literal[True]:
|
|
532
593
|
"""
|
|
533
594
|
Set RSE limit information.
|
|
534
595
|
|
|
@@ -536,7 +597,7 @@ class RSEClient(BaseClient):
|
|
|
536
597
|
:param name: The name of the limit.
|
|
537
598
|
:param value: The feature value.
|
|
538
599
|
|
|
539
|
-
:returns: True if successful
|
|
600
|
+
:returns: True if successful
|
|
540
601
|
"""
|
|
541
602
|
path = [self.RSE_BASEURL, rse, 'limits']
|
|
542
603
|
path = '/'.join(path)
|
|
@@ -549,13 +610,16 @@ class RSEClient(BaseClient):
|
|
|
549
610
|
data=r.content)
|
|
550
611
|
raise exc_cls(exc_msg)
|
|
551
612
|
|
|
552
|
-
def get_rse_limits(
|
|
613
|
+
def get_rse_limits(
|
|
614
|
+
self,
|
|
615
|
+
rse: str
|
|
616
|
+
) -> "Iterator[dict[str, Union[str, int]]]":
|
|
553
617
|
"""
|
|
554
618
|
Get RSE limits.
|
|
555
619
|
|
|
556
620
|
:param rse: The RSE name.
|
|
557
621
|
|
|
558
|
-
:returns:
|
|
622
|
+
:returns: An iterator of RSE limits as dicts with 'name' and 'value' as keys.
|
|
559
623
|
"""
|
|
560
624
|
path = [self.RSE_BASEURL, rse, 'limits']
|
|
561
625
|
path = '/'.join(path)
|
|
@@ -568,14 +632,14 @@ class RSEClient(BaseClient):
|
|
|
568
632
|
data=r.content)
|
|
569
633
|
raise exc_cls(exc_msg)
|
|
570
634
|
|
|
571
|
-
def delete_rse_limits(self, rse, name):
|
|
635
|
+
def delete_rse_limits(self, rse: str, name: str) -> Literal[True]:
|
|
572
636
|
"""
|
|
573
637
|
Delete RSE limit information.
|
|
574
638
|
|
|
575
639
|
:param rse: The RSE name.
|
|
576
640
|
:param name: The name of the limit.
|
|
577
641
|
|
|
578
|
-
:returns: True if successful
|
|
642
|
+
:returns: True if successful
|
|
579
643
|
"""
|
|
580
644
|
path = [self.RSE_BASEURL, rse, 'limits']
|
|
581
645
|
path = '/'.join(path)
|
|
@@ -587,15 +651,20 @@ class RSEClient(BaseClient):
|
|
|
587
651
|
status_code=r.status_code,
|
|
588
652
|
data=r.content)
|
|
589
653
|
|
|
590
|
-
|
|
654
|
+
raise exc_cls(exc_msg)
|
|
591
655
|
|
|
592
|
-
def add_distance(
|
|
656
|
+
def add_distance(
|
|
657
|
+
self,
|
|
658
|
+
source: str,
|
|
659
|
+
destination: str,
|
|
660
|
+
parameters: dict[str, int]
|
|
661
|
+
) -> Literal[True]:
|
|
593
662
|
"""
|
|
594
663
|
Add a src-dest distance.
|
|
595
664
|
|
|
596
665
|
:param source: The source.
|
|
597
666
|
:param destination: The destination.
|
|
598
|
-
:param parameters: A
|
|
667
|
+
:param parameters: A dictionary with property.
|
|
599
668
|
"""
|
|
600
669
|
path = [self.RSE_BASEURL, source, 'distances', destination]
|
|
601
670
|
path = '/'.join(path)
|
|
@@ -608,13 +677,18 @@ class RSEClient(BaseClient):
|
|
|
608
677
|
data=r.content)
|
|
609
678
|
raise exc_cls(exc_msg)
|
|
610
679
|
|
|
611
|
-
def update_distance(
|
|
680
|
+
def update_distance(
|
|
681
|
+
self,
|
|
682
|
+
source: str,
|
|
683
|
+
destination: str,
|
|
684
|
+
parameters: dict[str, int]
|
|
685
|
+
) -> Literal[True]:
|
|
612
686
|
"""
|
|
613
687
|
Update distances with the given RSE ids.
|
|
614
688
|
|
|
615
689
|
:param source: The source.
|
|
616
690
|
:param destination: The destination.
|
|
617
|
-
:param parameters: A
|
|
691
|
+
:param parameters: A dictionary with property.
|
|
618
692
|
"""
|
|
619
693
|
path = [self.RSE_BASEURL, source, 'distances', destination]
|
|
620
694
|
path = '/'.join(path)
|
|
@@ -627,7 +701,11 @@ class RSEClient(BaseClient):
|
|
|
627
701
|
data=r.content)
|
|
628
702
|
raise exc_cls(exc_msg)
|
|
629
703
|
|
|
630
|
-
def get_distance(
|
|
704
|
+
def get_distance(
|
|
705
|
+
self,
|
|
706
|
+
source: str,
|
|
707
|
+
destination: str
|
|
708
|
+
) -> list[dict[str, Union[str, int]]]:
|
|
631
709
|
"""
|
|
632
710
|
Get distances between rses.
|
|
633
711
|
|
|
@@ -645,7 +723,11 @@ class RSEClient(BaseClient):
|
|
|
645
723
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
646
724
|
raise exc_cls(exc_msg)
|
|
647
725
|
|
|
648
|
-
def delete_distance(
|
|
726
|
+
def delete_distance(
|
|
727
|
+
self,
|
|
728
|
+
source: str,
|
|
729
|
+
destination: str
|
|
730
|
+
) -> Literal[True]:
|
|
649
731
|
"""
|
|
650
732
|
Delete distances with the given RSE ids.
|
|
651
733
|
|
rucio/client/ruleclient.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -14,15 +13,17 @@
|
|
|
14
13
|
# limitations under the License.
|
|
15
14
|
|
|
16
15
|
from json import dumps, loads
|
|
17
|
-
from typing import Any, Optional, Union
|
|
16
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, Union
|
|
18
17
|
from urllib.parse import quote_plus
|
|
19
18
|
|
|
20
19
|
from requests.status_codes import codes
|
|
21
20
|
|
|
22
|
-
from rucio.client.baseclient import BaseClient
|
|
23
|
-
from rucio.client.baseclient import choice
|
|
21
|
+
from rucio.client.baseclient import BaseClient, choice
|
|
24
22
|
from rucio.common.utils import build_url
|
|
25
23
|
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from collections.abc import Iterator, Mapping, Sequence
|
|
26
|
+
|
|
26
27
|
|
|
27
28
|
class RuleClient(BaseClient):
|
|
28
29
|
|
|
@@ -32,7 +33,7 @@ class RuleClient(BaseClient):
|
|
|
32
33
|
|
|
33
34
|
def add_replication_rule(
|
|
34
35
|
self,
|
|
35
|
-
dids:
|
|
36
|
+
dids: "Sequence[dict[str, str]]",
|
|
36
37
|
copies: int,
|
|
37
38
|
rse_expression: str,
|
|
38
39
|
priority: int = 3,
|
|
@@ -48,10 +49,10 @@ class RuleClient(BaseClient):
|
|
|
48
49
|
ask_approval: bool = False,
|
|
49
50
|
asynchronous: bool = False,
|
|
50
51
|
locked: bool = False,
|
|
51
|
-
delay_injection=None,
|
|
52
|
-
comment=None,
|
|
53
|
-
weight=None,
|
|
54
|
-
):
|
|
52
|
+
delay_injection: Optional[int] = None,
|
|
53
|
+
comment: Optional[str] = None,
|
|
54
|
+
weight: Optional[int] = None,
|
|
55
|
+
) -> Any:
|
|
55
56
|
"""
|
|
56
57
|
:param dids: The data identifier set.
|
|
57
58
|
:param copies: The number of replicas.
|
|
@@ -92,7 +93,7 @@ class RuleClient(BaseClient):
|
|
|
92
93
|
|
|
93
94
|
def delete_replication_rule(
|
|
94
95
|
self, rule_id: str, purge_replicas: Optional[bool] = None
|
|
95
|
-
):
|
|
96
|
+
) -> Literal[True]:
|
|
96
97
|
"""
|
|
97
98
|
Deletes a replication rule and all associated locks.
|
|
98
99
|
|
|
@@ -113,7 +114,7 @@ class RuleClient(BaseClient):
|
|
|
113
114
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
114
115
|
raise exc_cls(exc_msg)
|
|
115
116
|
|
|
116
|
-
def get_replication_rule(self, rule_id: str):
|
|
117
|
+
def get_replication_rule(self, rule_id: str) -> Any:
|
|
117
118
|
"""
|
|
118
119
|
Get a replication rule.
|
|
119
120
|
|
|
@@ -129,7 +130,7 @@ class RuleClient(BaseClient):
|
|
|
129
130
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
130
131
|
raise exc_cls(exc_msg)
|
|
131
132
|
|
|
132
|
-
def update_replication_rule(self, rule_id: str, options: dict[str, Any]):
|
|
133
|
+
def update_replication_rule(self, rule_id: str, options: dict[str, Any]) -> Literal[True]:
|
|
133
134
|
"""
|
|
134
135
|
:param rule_id: The id of the rule to be retrieved.
|
|
135
136
|
:param options: Options dictionary.
|
|
@@ -145,8 +146,11 @@ class RuleClient(BaseClient):
|
|
|
145
146
|
raise exc_cls(exc_msg)
|
|
146
147
|
|
|
147
148
|
def reduce_replication_rule(
|
|
148
|
-
self,
|
|
149
|
-
|
|
149
|
+
self,
|
|
150
|
+
rule_id: str,
|
|
151
|
+
copies: int,
|
|
152
|
+
exclude_expression: Optional[str] = None
|
|
153
|
+
) -> Any:
|
|
150
154
|
"""
|
|
151
155
|
:param rule_id: Rule to be reduced.
|
|
152
156
|
:param copies: Number of copies of the new rule.
|
|
@@ -164,8 +168,11 @@ class RuleClient(BaseClient):
|
|
|
164
168
|
raise exc_cls(exc_msg)
|
|
165
169
|
|
|
166
170
|
def move_replication_rule(
|
|
167
|
-
self,
|
|
168
|
-
|
|
171
|
+
self,
|
|
172
|
+
rule_id: str,
|
|
173
|
+
rse_expression: str,
|
|
174
|
+
override: "Mapping[str, Any]"
|
|
175
|
+
) -> Any:
|
|
169
176
|
"""
|
|
170
177
|
Move a replication rule to another RSE and, once done, delete the original one.
|
|
171
178
|
|
|
@@ -188,7 +195,7 @@ class RuleClient(BaseClient):
|
|
|
188
195
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
189
196
|
raise exc_cls(exc_msg)
|
|
190
197
|
|
|
191
|
-
def approve_replication_rule(self, rule_id: str):
|
|
198
|
+
def approve_replication_rule(self, rule_id: str) -> Literal[True]:
|
|
192
199
|
"""
|
|
193
200
|
:param rule_id: Rule to be approved.
|
|
194
201
|
:raises: RuleNotFound
|
|
@@ -203,7 +210,7 @@ class RuleClient(BaseClient):
|
|
|
203
210
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
204
211
|
raise exc_cls(exc_msg)
|
|
205
212
|
|
|
206
|
-
def deny_replication_rule(self, rule_id: str, reason: Optional[str] = None):
|
|
213
|
+
def deny_replication_rule(self, rule_id: str, reason: Optional[str] = None) -> Literal[True]:
|
|
207
214
|
"""
|
|
208
215
|
:param rule_id: Rule to be denied.
|
|
209
216
|
:param reason: Reason for denying the rule.
|
|
@@ -224,7 +231,7 @@ class RuleClient(BaseClient):
|
|
|
224
231
|
|
|
225
232
|
def list_replication_rule_full_history(
|
|
226
233
|
self, scope: Union[str, bytes], name: Union[str, bytes]
|
|
227
|
-
):
|
|
234
|
+
) -> "Iterator[dict[str, Any]]":
|
|
228
235
|
"""
|
|
229
236
|
List the rule history of a DID.
|
|
230
237
|
|
|
@@ -239,7 +246,7 @@ class RuleClient(BaseClient):
|
|
|
239
246
|
exc_cls, exc_msg = self._get_exception(r.headers, r.status_code)
|
|
240
247
|
raise exc_cls(exc_msg)
|
|
241
248
|
|
|
242
|
-
def examine_replication_rule(self, rule_id: str):
|
|
249
|
+
def examine_replication_rule(self, rule_id: str) -> Any:
|
|
243
250
|
"""
|
|
244
251
|
Examine a replication rule for errors during transfer.
|
|
245
252
|
|
|
@@ -254,7 +261,7 @@ class RuleClient(BaseClient):
|
|
|
254
261
|
exc_cls, exc_msg = self._get_exception(r.headers, r.status_code)
|
|
255
262
|
raise exc_cls(exc_msg)
|
|
256
263
|
|
|
257
|
-
def list_replica_locks(self, rule_id: str):
|
|
264
|
+
def list_replica_locks(self, rule_id: str) -> Any:
|
|
258
265
|
"""
|
|
259
266
|
List details of all replica locks for a rule.
|
|
260
267
|
|
|
@@ -269,7 +276,7 @@ class RuleClient(BaseClient):
|
|
|
269
276
|
exc_cls, exc_msg = self._get_exception(r.headers, r.status_code)
|
|
270
277
|
raise exc_cls(exc_msg)
|
|
271
278
|
|
|
272
|
-
def list_replication_rules(self, filters=None):
|
|
279
|
+
def list_replication_rules(self, filters: Optional[dict[str, Any]] = None) -> "Iterator[dict[str, Any]]":
|
|
273
280
|
"""
|
|
274
281
|
List all replication rules which match a filter
|
|
275
282
|
:param filters: dictionary of attributes by which the rules should be filtered
|
rucio/client/scopeclient.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
1
|
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
3
2
|
#
|
|
4
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -18,8 +17,7 @@ from urllib.parse import quote_plus
|
|
|
18
17
|
|
|
19
18
|
from requests.status_codes import codes
|
|
20
19
|
|
|
21
|
-
from rucio.client.baseclient import BaseClient
|
|
22
|
-
from rucio.client.baseclient import choice
|
|
20
|
+
from rucio.client.baseclient import BaseClient, choice
|
|
23
21
|
from rucio.common.utils import build_url
|
|
24
22
|
|
|
25
23
|
|
|
@@ -29,7 +27,11 @@ class ScopeClient(BaseClient):
|
|
|
29
27
|
|
|
30
28
|
SCOPE_BASEURL = 'accounts'
|
|
31
29
|
|
|
32
|
-
def add_scope(
|
|
30
|
+
def add_scope(
|
|
31
|
+
self,
|
|
32
|
+
account: str,
|
|
33
|
+
scope: str
|
|
34
|
+
) -> bool:
|
|
33
35
|
"""
|
|
34
36
|
Sends the request to add a new scope.
|
|
35
37
|
|
|
@@ -49,7 +51,7 @@ class ScopeClient(BaseClient):
|
|
|
49
51
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
50
52
|
raise exc_cls(exc_msg)
|
|
51
53
|
|
|
52
|
-
def list_scopes(self):
|
|
54
|
+
def list_scopes(self) -> list[str]:
|
|
53
55
|
"""
|
|
54
56
|
Sends the request to list all scopes.
|
|
55
57
|
|
|
@@ -66,7 +68,7 @@ class ScopeClient(BaseClient):
|
|
|
66
68
|
exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
|
|
67
69
|
raise exc_cls(exc_msg)
|
|
68
70
|
|
|
69
|
-
def list_scopes_for_account(self, account):
|
|
71
|
+
def list_scopes_for_account(self, account: str) -> list[str]:
|
|
70
72
|
"""
|
|
71
73
|
Sends the request to list all scopes for a rucio account.
|
|
72
74
|
|