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.
@@ -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
- # Site = # List of CEs that will be treated by this SiteDirector (No value can refer to any CE defined in the CS)
267
- # CEs = # List of CE types that will be treated by this SiteDirector (No value can refer to any type of CE defined in the CS)
268
- # CETypes = # List of Tags that are required to be present in the CE/Queue definition
269
- # Tags =
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.7
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.7
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=ZrQEMRFEfCTTkbcaio6DLV1dijp4e8gJgO8kvphW9p4,40045
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=PwdHIHEJpP4I7plHRhrIBHrftIW0aRHCasYx7AUQfd4,15432
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=lCelD92HtTXp46CCwCb8S58BjITG1fBgtFs116vehww,8949
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=7b0CVkSgJ9b_lX-6CT6exzaWgEHH6pLjj5T1RJTnYJU,45114
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.7.dist-info/licenses/LICENSE,sha256=uyr4oV6jmjUeepXZPPjkJRwa5q5MrI7jqJz5sVXNblQ,32452
1299
- dirac-9.0.7.dist-info/METADATA,sha256=0Y2bxOpUIA4SmXbeMd2Lp1_MLU8_2m83KFlge8LwsLs,10016
1300
- dirac-9.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1301
- dirac-9.0.7.dist-info/entry_points.txt,sha256=hupzIL8aVmjK3nn7RLKdhcaiPmLOiD3Kulh3CSDHKmw,16492
1302
- dirac-9.0.7.dist-info/top_level.txt,sha256=RISrnN9kb_mPqmVu8_o4jF-DSX8-h6AcgfkO9cgfkHA,6
1303
- dirac-9.0.7.dist-info/RECORD,,
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