DIRAC 9.0.7__py3-none-any.whl → 9.0.8__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.
- DIRAC/DataManagementSystem/Client/FTS3Job.py +54 -1
- DIRAC/DataManagementSystem/Client/test/Test_FTS3Objects.py +1 -0
- DIRAC/DataManagementSystem/Client/test/Test_scitag.py +69 -0
- DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py +4 -4
- DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg +8 -4
- {dirac-9.0.7.dist-info → dirac-9.0.8.dist-info}/METADATA +2 -2
- {dirac-9.0.7.dist-info → dirac-9.0.8.dist-info}/RECORD +11 -10
- {dirac-9.0.7.dist-info → dirac-9.0.8.dist-info}/WHEEL +0 -0
- {dirac-9.0.7.dist-info → dirac-9.0.8.dist-info}/entry_points.txt +0 -0
- {dirac-9.0.7.dist-info → dirac-9.0.8.dist-info}/licenses/LICENSE +0 -0
- {dirac-9.0.7.dist-info → dirac-9.0.8.dist-info}/top_level.txt +0 -0
|
@@ -3,9 +3,13 @@
|
|
|
3
3
|
import datetime
|
|
4
4
|
import errno
|
|
5
5
|
import os
|
|
6
|
+
import requests
|
|
6
7
|
from packaging.version import Version
|
|
7
8
|
|
|
8
|
-
from cachetools import cachedmethod, LRUCache
|
|
9
|
+
from cachetools import cachedmethod, LRUCache, TTLCache, cached
|
|
10
|
+
from threading import Lock
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
9
13
|
|
|
10
14
|
# Requires at least version 3.3.3
|
|
11
15
|
from fts3 import __version__ as fts3_version
|
|
@@ -44,6 +48,50 @@ BRING_ONLINE_TIMEOUT = 259200
|
|
|
44
48
|
IDP_CACHE_SIZE = 8
|
|
45
49
|
|
|
46
50
|
|
|
51
|
+
_scitag_cache = TTLCache(maxsize=10, ttl=3600)
|
|
52
|
+
_scitag_lock = Lock()
|
|
53
|
+
_scitag_json_cache = TTLCache(maxsize=1, ttl=86400)
|
|
54
|
+
_scitag_json_lock = Lock()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@cached(_scitag_cache, lock=_scitag_lock)
|
|
58
|
+
def get_scitag(vo: str, activity: Optional[str] = None) -> int:
|
|
59
|
+
"""
|
|
60
|
+
Get the scitag based on the VO and activity.
|
|
61
|
+
If the VO is not found in the scitag.json, it defaults to 1.
|
|
62
|
+
If no specific activity is provided, it defaults to the "default" activityName.
|
|
63
|
+
|
|
64
|
+
:param vo: The VO for which to get the scitag
|
|
65
|
+
:param activity: The activity for which to get the scitag
|
|
66
|
+
:return: The scitag value
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
@cached(_scitag_json_cache, lock=_scitag_json_lock)
|
|
70
|
+
def get_remote_json():
|
|
71
|
+
gLogger.verbose("Fetching https://scitags.org/api.json from the network")
|
|
72
|
+
response = requests.get("https://scitags.org/api.json")
|
|
73
|
+
response.raise_for_status()
|
|
74
|
+
return response.json()
|
|
75
|
+
|
|
76
|
+
vo_id = 1 # Default VO ID
|
|
77
|
+
activity_id = 1 # Default activity ID
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
# Load the JSON data from the cache or network
|
|
81
|
+
sj = get_remote_json()
|
|
82
|
+
|
|
83
|
+
for experiment in sj.get("experiments", []):
|
|
84
|
+
if experiment.get("expName") == vo.lower():
|
|
85
|
+
vo_id = experiment.get("expId")
|
|
86
|
+
for act in experiment.get("activities", []):
|
|
87
|
+
if act.get("activityName") == activity:
|
|
88
|
+
activity_id = act.get("activityId")
|
|
89
|
+
except Exception as e:
|
|
90
|
+
gLogger.error(f"Error fetching or parsing scitag.json. Using default scitag values.", repr(e))
|
|
91
|
+
# Logic to determine the scitag based on vo and activity (this is what FTS wants)
|
|
92
|
+
return vo_id << 6 | activity_id # Example logic, replace with actual implementation
|
|
93
|
+
|
|
94
|
+
|
|
47
95
|
class FTS3Job(JSerializable):
|
|
48
96
|
"""Abstract class to represent a job to be executed by FTS. It belongs
|
|
49
97
|
to an FTS3Operation
|
|
@@ -470,6 +518,9 @@ class FTS3Job(JSerializable):
|
|
|
470
518
|
|
|
471
519
|
ftsFileID = getattr(ftsFile, "fileID")
|
|
472
520
|
|
|
521
|
+
# scitag 65 is 1 << 6 | 1 (default experiment, default activity)
|
|
522
|
+
scitag = get_scitag(vo=self.vo, activity=self.activity)
|
|
523
|
+
|
|
473
524
|
# Under normal circumstances, we simply submit an fts transfer as such:
|
|
474
525
|
# * srcProto://myFile -> destProto://myFile
|
|
475
526
|
#
|
|
@@ -499,6 +550,7 @@ class FTS3Job(JSerializable):
|
|
|
499
550
|
filesize=ftsFile.size,
|
|
500
551
|
metadata=stageTrans_metadata,
|
|
501
552
|
activity=self.activity,
|
|
553
|
+
scitag=scitag,
|
|
502
554
|
)
|
|
503
555
|
transfers.append(stageTrans)
|
|
504
556
|
|
|
@@ -572,6 +624,7 @@ class FTS3Job(JSerializable):
|
|
|
572
624
|
activity=self.activity,
|
|
573
625
|
source_token=srcToken,
|
|
574
626
|
destination_token=dstToken,
|
|
627
|
+
scitag=scitag,
|
|
575
628
|
)
|
|
576
629
|
|
|
577
630
|
transfers.append(trans)
|
|
@@ -204,6 +204,7 @@ def generateFTS3Job(sourceSE, targetSE, lfns, multiHopSE=None):
|
|
|
204
204
|
newJob.sourceSE = sourceSE
|
|
205
205
|
newJob.targetSE = targetSE
|
|
206
206
|
newJob.multiHopSE = multiHopSE
|
|
207
|
+
newJob.vo = "lhcb"
|
|
207
208
|
filesToSubmit = []
|
|
208
209
|
|
|
209
210
|
for i, lfn in enumerate(lfns, start=1):
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from unittest.mock import Mock, patch
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from DIRAC.DataManagementSystem.Client.FTS3Job import get_scitag
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestGetScitag:
|
|
9
|
+
def test_valid_vo_and_activity(self):
|
|
10
|
+
"""Test get_scitag with valid VO and activity."""
|
|
11
|
+
result = get_scitag("atlas", "Analysis Input")
|
|
12
|
+
expected = 2 << 6 | 17 # atlas expId=2, analysis activityId=17
|
|
13
|
+
assert result == expected
|
|
14
|
+
|
|
15
|
+
def test_valid_vo_no_activity(self):
|
|
16
|
+
"""Test get_scitag with valid VO but no specific activity (should use default)."""
|
|
17
|
+
result = get_scitag("cms")
|
|
18
|
+
expected = 3 << 6 | 1 # cms expId=200, default activityId=1
|
|
19
|
+
assert result == expected
|
|
20
|
+
|
|
21
|
+
def test_invalid_vo(self):
|
|
22
|
+
"""Test get_scitag with invalid VO (should use default vo_id=1)."""
|
|
23
|
+
result = get_scitag("nonexistent")
|
|
24
|
+
expected = 1 << 6 | 1 # default vo_id=1, default activity_id=1
|
|
25
|
+
assert result == expected
|
|
26
|
+
|
|
27
|
+
def test_valid_vo_invalid_activity(self):
|
|
28
|
+
"""Test get_scitag with valid VO but invalid activity."""
|
|
29
|
+
result = get_scitag("atlas", "nonexistent_activity")
|
|
30
|
+
expected = 2 << 6 | 1 # atlas expId=2, default activity_id=1
|
|
31
|
+
assert result == expected
|
|
32
|
+
|
|
33
|
+
def test_case_insensitive_vo(self):
|
|
34
|
+
"""Test that VO matching is case insensitive."""
|
|
35
|
+
result = get_scitag("ATLAS", "Data Brokering")
|
|
36
|
+
expected = 2 << 6 | 3 # atlas expId=2, production activityId=3
|
|
37
|
+
assert result == expected
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.parametrize(
|
|
41
|
+
"vo,activity,expected_vo_id,expected_activity_id",
|
|
42
|
+
[
|
|
43
|
+
("atlas", "Analysis Output", 2, 18),
|
|
44
|
+
("atlas", "Debug", 2, 9),
|
|
45
|
+
("cms", "Cache", 3, 3),
|
|
46
|
+
("cms", "default", 3, 1),
|
|
47
|
+
("nonexistent", "any", 1, 1), # defaults
|
|
48
|
+
("atlas", "nonexistent", 2, 1), # valid vo, invalid activity
|
|
49
|
+
],
|
|
50
|
+
)
|
|
51
|
+
def test_parametrized_scenarios(vo, activity, expected_vo_id, expected_activity_id):
|
|
52
|
+
"""Parametrized test for various VO and activity combinations."""
|
|
53
|
+
result = get_scitag(vo, activity)
|
|
54
|
+
expected = expected_vo_id << 6 | expected_activity_id
|
|
55
|
+
assert result == expected
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@pytest.mark.parametrize(
|
|
59
|
+
"vo,expected_result",
|
|
60
|
+
[
|
|
61
|
+
("atlas", 2 << 6 | 1), # Should use default activity
|
|
62
|
+
("cms", 3 << 6 | 1), # Should use default activity
|
|
63
|
+
("unknown", 1 << 6 | 1), # Should use all defaults
|
|
64
|
+
],
|
|
65
|
+
)
|
|
66
|
+
def test_no_activity_parameter(vo, expected_result):
|
|
67
|
+
"""Test behavior when no activity parameter is provided."""
|
|
68
|
+
result = get_scitag(vo)
|
|
69
|
+
assert result == expected_result
|
|
@@ -148,10 +148,10 @@ class SiteDirector(AgentModule):
|
|
|
148
148
|
self.sendSubmissionAccounting = True
|
|
149
149
|
|
|
150
150
|
# Get the site description dictionary
|
|
151
|
-
siteNames = self.am_getOption("Site")
|
|
152
|
-
ceTypes = self.am_getOption("CETypes")
|
|
153
|
-
ces = self.am_getOption("CEs")
|
|
154
|
-
tags = self.am_getOption("Tags")
|
|
151
|
+
siteNames = self.am_getOption("Site", []) or None
|
|
152
|
+
ceTypes = self.am_getOption("CETypes", []) or None
|
|
153
|
+
ces = self.am_getOption("CEs", []) or None
|
|
154
|
+
tags = self.am_getOption("Tags", []) or None
|
|
155
155
|
|
|
156
156
|
# Display options used
|
|
157
157
|
self.log.always("VO:", self.vo)
|
|
@@ -263,10 +263,14 @@ Agents
|
|
|
263
263
|
# the DN of the certificate proxy used to submit pilots. If not found here, what is in Operations/Pilot section of the CS will be used
|
|
264
264
|
PilotDN =
|
|
265
265
|
|
|
266
|
-
#
|
|
267
|
-
|
|
268
|
-
#
|
|
269
|
-
|
|
266
|
+
# List of Sites that will be treated by this SiteDirector (No value can refer to any CE defined in the CS)
|
|
267
|
+
Site =
|
|
268
|
+
# List of CEs that will be treated by this SiteDirector (No value can refer to any type of CE defined in the CS)
|
|
269
|
+
CEs =
|
|
270
|
+
# List of CETypes that are required to be present in the CE/Queue definition
|
|
271
|
+
CETypes =
|
|
272
|
+
# List of Tags that are required to be present in the CE/Queue definition
|
|
273
|
+
Tags =
|
|
270
274
|
|
|
271
275
|
# How many cycles to skip if queue is not working
|
|
272
276
|
FailedQueueCycleFactor = 10
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: DIRAC
|
|
3
|
-
Version: 9.0.
|
|
3
|
+
Version: 9.0.8
|
|
4
4
|
Summary: DIRAC is an interware, meaning a software framework for distributed computing.
|
|
5
5
|
Home-page: https://github.com/DIRACGrid/DIRAC/
|
|
6
6
|
License: GPL-3.0-only
|
|
@@ -19,7 +19,7 @@ Requires-Dist: cachetools
|
|
|
19
19
|
Requires-Dist: certifi
|
|
20
20
|
Requires-Dist: cwltool
|
|
21
21
|
Requires-Dist: diraccfg
|
|
22
|
-
Requires-Dist: DIRACCommon==v9.0.
|
|
22
|
+
Requires-Dist: DIRACCommon==v9.0.8
|
|
23
23
|
Requires-Dist: diracx-client>=v0.0.1
|
|
24
24
|
Requires-Dist: diracx-core>=v0.0.1
|
|
25
25
|
Requires-Dist: diracx-cli>=v0.0.1
|
|
@@ -365,7 +365,7 @@ DIRAC/DataManagementSystem/Client/DataManager.py,sha256=edLmRUHJtZEYAMyen3y9qwdG
|
|
|
365
365
|
DIRAC/DataManagementSystem/Client/DirectoryListing.py,sha256=CvQZ5Da5WhgwdDL8iLk0xVBjKZrBHTdwMKWwSJwzwEI,7582
|
|
366
366
|
DIRAC/DataManagementSystem/Client/FTS3Client.py,sha256=Kk1wy4YnkYuOI6IltyDYZqkzxV7Zsf7ZuoKT12_VbTw,3531
|
|
367
367
|
DIRAC/DataManagementSystem/Client/FTS3File.py,sha256=gZFN_Uxc2tblUCETb4qWPJ2M1tSmKUvTMiZUL-yJ6M0,3122
|
|
368
|
-
DIRAC/DataManagementSystem/Client/FTS3Job.py,sha256=
|
|
368
|
+
DIRAC/DataManagementSystem/Client/FTS3Job.py,sha256=5MAtSZoWb_rwglNHdYJAuoXzoW5_TAX96E5jUWEYds8,42090
|
|
369
369
|
DIRAC/DataManagementSystem/Client/FTS3Operation.py,sha256=L3yqc0X0ziluMPegoQU6o3aYDnTYwLtujShgbGFJjsw,24455
|
|
370
370
|
DIRAC/DataManagementSystem/Client/FailoverTransfer.py,sha256=2V-dKtgAndMuw9iZHYV019V0hLwlezUNP33wvClpsaA,13373
|
|
371
371
|
DIRAC/DataManagementSystem/Client/FileCatalogClientCLI.py,sha256=sc_6mT0BCbXgj5wOEFtCxNc0AvyQ186A_yLi2lnduvw,80094
|
|
@@ -376,7 +376,8 @@ DIRAC/DataManagementSystem/Client/CmdDirCompletion/AbstractFileSystem.py,sha256=
|
|
|
376
376
|
DIRAC/DataManagementSystem/Client/CmdDirCompletion/DirectoryCompletion.py,sha256=TdOCEfVQ3QppTl0iHrf472rT3YkDw2EX2sUviKIYL2s,2394
|
|
377
377
|
DIRAC/DataManagementSystem/Client/CmdDirCompletion/__init__.py,sha256=IU_DNOfkPtg8iBqQatUKTNBMj2LldGrhf6KseBgx14M,236
|
|
378
378
|
DIRAC/DataManagementSystem/Client/test/Test_Client_DataManagementSystem.py,sha256=qb0mERTlHOysiSfNPDsbLbadWgbuQLulT9Py8RqTIYc,3956
|
|
379
|
-
DIRAC/DataManagementSystem/Client/test/Test_FTS3Objects.py,sha256=
|
|
379
|
+
DIRAC/DataManagementSystem/Client/test/Test_FTS3Objects.py,sha256=DZHRZPfiTJrqinXolneRE06Wf51sVtRw0Fx0bq85AAA,15455
|
|
380
|
+
DIRAC/DataManagementSystem/Client/test/Test_scitag.py,sha256=llvY98ODaBZhyhDquP9IMzCB-uXJz8xL-TO2-sbNf68,2545
|
|
380
381
|
DIRAC/DataManagementSystem/Client/test/__init__.py,sha256=IL2xDyzb5nr2dkH2hpT4Zx6vvc9m4jDryuUmfyIY_RY,58
|
|
381
382
|
DIRAC/DataManagementSystem/Client/test/mock_DM.py,sha256=S7qWHjN3ZyjqKIjHkXwuUWJqp75waEchc1IsNB9y-28,1167
|
|
382
383
|
DIRAC/DataManagementSystem/Client/test/new_dir_completion.py,sha256=_Km7jE4IRe-pY8BJ62hK6IbwRROoj0wxvL7WMClEJ0E,1212
|
|
@@ -1118,7 +1119,7 @@ DIRAC/Workflow/Modules/test/Test_Modules.py,sha256=d92bA2SpF7Wwg9gy3roEvPt_7QlnB
|
|
|
1118
1119
|
DIRAC/Workflow/Utilities/Utils.py,sha256=9f395ylWaLRaaC6EExPAyvOhPK3FXD7I_XGevqueRkM,2545
|
|
1119
1120
|
DIRAC/Workflow/Utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1120
1121
|
DIRAC/Workflow/Utilities/test/Test_Utilities.py,sha256=DNjFPpBmpojwCWhZSUSoG3AIhMQvqyiZdSuVkrHkOtk,2595
|
|
1121
|
-
DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg,sha256=
|
|
1122
|
+
DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg,sha256=uHa3ZiSC7cyhbJUNvWwqiL0E-m9UmBinrLIQdWmre3k,9030
|
|
1122
1123
|
DIRAC/WorkloadManagementSystem/__init__.py,sha256=9-_-HOT_8S3i-TMmTR_gFVVlNyktBRk-S2qSuOBKoIc,50
|
|
1123
1124
|
DIRAC/WorkloadManagementSystem/Agent/JobAgent.py,sha256=LzLypd3m4a6M-J5_nmUMsMqgflb_1Xm77eONDE6G1Vg,40843
|
|
1124
1125
|
DIRAC/WorkloadManagementSystem/Agent/JobCleaningAgent.py,sha256=TR8nDO43DuJxOQVIdOUrqpWjRjJp52dVzOKUUewL9U4,14708
|
|
@@ -1126,7 +1127,7 @@ DIRAC/WorkloadManagementSystem/Agent/PilotLoggingAgent.py,sha256=ZIgvFpasGTh76GW
|
|
|
1126
1127
|
DIRAC/WorkloadManagementSystem/Agent/PilotStatusAgent.py,sha256=qY6TbYCPOFFXhHffmRJLNEbWvZPyg5Lc5B_8BbyQ7zc,9711
|
|
1127
1128
|
DIRAC/WorkloadManagementSystem/Agent/PilotSyncAgent.py,sha256=qzDFCGZ8EtjxDUaPgyFDlSmJfyF2KLuyXTC7au3-p2Q,4860
|
|
1128
1129
|
DIRAC/WorkloadManagementSystem/Agent/PushJobAgent.py,sha256=IvHshnw2xN0AZrruEu86C47GDez8enBD6jjNIZd6QcA,38594
|
|
1129
|
-
DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py,sha256=
|
|
1130
|
+
DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py,sha256=ZSGWVKO64ztnv_R19I6TT7660jf7LMuYcff_aPq2xCM,45162
|
|
1130
1131
|
DIRAC/WorkloadManagementSystem/Agent/StalledJobAgent.py,sha256=foEbmRotEmfeQG6nyIsJv1kSJkm4flkQsPYbSylS3SM,24572
|
|
1131
1132
|
DIRAC/WorkloadManagementSystem/Agent/StatesAccountingAgent.py,sha256=iNIlWQEDBk6R1S8oHOIusZUwxOwLtgwuzR_4s32-o5w,8707
|
|
1132
1133
|
DIRAC/WorkloadManagementSystem/Agent/TaskQueuesAgent.py,sha256=ypsmo233TFXq9IC5uz6pum7_joOh2gFPUYNmmCpukAY,943
|
|
@@ -1295,9 +1296,9 @@ DIRAC/tests/Workflow/Integration/exe-script.py,sha256=B_slYdTocEzqfQLRhwuPiLyYUn
|
|
|
1295
1296
|
DIRAC/tests/Workflow/Integration/helloWorld.py,sha256=tBgEHH3ZF7ZiTS57gtmm3DW-Qxgm_57HWHpM-Y8XSws,205
|
|
1296
1297
|
DIRAC/tests/Workflow/Regression/helloWorld.py,sha256=69eCgFuVSYo-mK3Dj2dw1c6g86sF5FksKCf8V2aGVoM,509
|
|
1297
1298
|
DIRAC/tests/Workflow/Regression/helloWorld.xml,sha256=xwydIcFTAHIX-YPfQfyxuQ7hzvIO3IhR3UAF7ORgkGg,5310
|
|
1298
|
-
dirac-9.0.
|
|
1299
|
-
dirac-9.0.
|
|
1300
|
-
dirac-9.0.
|
|
1301
|
-
dirac-9.0.
|
|
1302
|
-
dirac-9.0.
|
|
1303
|
-
dirac-9.0.
|
|
1299
|
+
dirac-9.0.8.dist-info/licenses/LICENSE,sha256=uyr4oV6jmjUeepXZPPjkJRwa5q5MrI7jqJz5sVXNblQ,32452
|
|
1300
|
+
dirac-9.0.8.dist-info/METADATA,sha256=gpKRR8YAjDBxrxogcUUGPNXojPku4FhNUVqBVSPRNWg,10016
|
|
1301
|
+
dirac-9.0.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
1302
|
+
dirac-9.0.8.dist-info/entry_points.txt,sha256=hupzIL8aVmjK3nn7RLKdhcaiPmLOiD3Kulh3CSDHKmw,16492
|
|
1303
|
+
dirac-9.0.8.dist-info/top_level.txt,sha256=RISrnN9kb_mPqmVu8_o4jF-DSX8-h6AcgfkO9cgfkHA,6
|
|
1304
|
+
dirac-9.0.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|