DIRAC 9.0.1__py3-none-any.whl → 9.0.4__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.
Files changed (28) hide show
  1. DIRAC/ConfigurationSystem/Client/Helpers/CSGlobals.py +0 -9
  2. DIRAC/ConfigurationSystem/Client/Helpers/Registry.py +3 -29
  3. DIRAC/ConfigurationSystem/Client/SyncPlugins/CERNLDAPSyncPlugin.py +4 -1
  4. DIRAC/Core/DISET/ServiceReactor.py +11 -3
  5. DIRAC/Core/Security/DiracX.py +11 -6
  6. DIRAC/Core/Security/test/test_diracx_token_from_pem.py +161 -0
  7. DIRAC/Core/Tornado/Server/TornadoService.py +1 -1
  8. DIRAC/Core/Utilities/test/Test_Profiler.py +20 -20
  9. DIRAC/FrameworkSystem/DB/ProxyDB.py +3 -3
  10. DIRAC/FrameworkSystem/scripts/dirac_login.py +2 -2
  11. DIRAC/FrameworkSystem/scripts/dirac_proxy_init.py +1 -1
  12. DIRAC/MonitoringSystem/DB/MonitoringDB.py +6 -5
  13. DIRAC/MonitoringSystem/Service/WebAppHandler.py +13 -3
  14. DIRAC/MonitoringSystem/private/MainReporter.py +0 -3
  15. DIRAC/Resources/IdProvider/CheckInIdProvider.py +13 -0
  16. DIRAC/TransformationSystem/Utilities/ReplicationCLIParameters.py +3 -3
  17. DIRAC/TransformationSystem/scripts/dirac_production_runjoblocal.py +2 -4
  18. DIRAC/TransformationSystem/test/Test_replicationTransformation.py +5 -6
  19. DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py +2 -6
  20. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_SiteDirector.py +8 -2
  21. DIRAC/WorkloadManagementSystem/DB/JobParametersDB.py +8 -8
  22. DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py +1 -1
  23. {dirac-9.0.1.dist-info → dirac-9.0.4.dist-info}/METADATA +5 -5
  24. {dirac-9.0.1.dist-info → dirac-9.0.4.dist-info}/RECORD +28 -27
  25. {dirac-9.0.1.dist-info → dirac-9.0.4.dist-info}/WHEEL +0 -0
  26. {dirac-9.0.1.dist-info → dirac-9.0.4.dist-info}/entry_points.txt +0 -0
  27. {dirac-9.0.1.dist-info → dirac-9.0.4.dist-info}/licenses/LICENSE +0 -0
  28. {dirac-9.0.1.dist-info → dirac-9.0.4.dist-info}/top_level.txt +0 -0
@@ -4,15 +4,6 @@ Some Helper functions to retrieve common location from the CS
4
4
  from DIRAC.Core.Utilities.Extensions import extensionsByPriority
5
5
 
6
6
 
7
- def getSetup() -> str:
8
- """
9
- Return setup name
10
- """
11
- from DIRAC import gConfig
12
-
13
- return gConfig.getValue("/DIRAC/Setup", "")
14
-
15
-
16
7
  def getVO(defaultVO: str = "") -> str:
17
8
  """
18
9
  Return VO from configuration
@@ -3,18 +3,14 @@
3
3
  import errno
4
4
  import inspect
5
5
  import sys
6
-
7
- from threading import Lock
8
6
  from collections.abc import Iterable
7
+ from threading import Lock
8
+ from typing import Optional
9
9
 
10
10
  from cachetools import TTLCache, cached
11
11
  from cachetools.keys import hashkey
12
12
 
13
-
14
- from typing import Optional
15
- from collections.abc import Iterable
16
-
17
- from DIRAC import S_OK, S_ERROR
13
+ from DIRAC import S_ERROR, S_OK
18
14
  from DIRAC.ConfigurationSystem.Client.Config import gConfig
19
15
  from DIRAC.ConfigurationSystem.Client.Helpers.CSGlobals import getVO
20
16
 
@@ -488,28 +484,6 @@ def getVOMSAttributeForGroup(group):
488
484
  return gConfig.getValue(f"{gBaseRegistrySection}/Groups/{group}/VOMSRole", getDefaultVOMSAttribute())
489
485
 
490
486
 
491
- def getDefaultVOMSVO():
492
- """Get default VOMS VO
493
-
494
- :return: str
495
- """
496
- return gConfig.getValue(f"{gBaseRegistrySection}/DefaultVOMSVO", "") or getVO()
497
-
498
-
499
- def getVOMSVOForGroup(group):
500
- """Search VOMS VO for group
501
-
502
- :param str group: group name
503
-
504
- :return: str
505
- """
506
- vomsVO = gConfig.getValue(f"{gBaseRegistrySection}/Groups/{group}/VOMSVO", getDefaultVOMSVO())
507
- if not vomsVO:
508
- vo = getVOForGroup(group)
509
- vomsVO = getVOOption(vo, "VOMSName", "")
510
- return vomsVO
511
-
512
-
513
487
  def getGroupsWithVOMSAttribute(vomsAttr):
514
488
  """Search groups with VOMS attribute
515
489
 
@@ -32,6 +32,9 @@ class CERNLDAPSyncPlugin:
32
32
  else:
33
33
  userDict["PrimaryCERNAccount"] = self._findOwnerAccountName(username, attributes)
34
34
 
35
+ if userDict["CERNAccountType"] in ["Primary", "Secondary"]:
36
+ userDict["CERNPersonId"] = attributes.get("employeeId", [None])[0]
37
+
35
38
  def _findOwnerAccountName(self, username, attributes):
36
39
  """Find the owner account from a CERN LDAP entry.
37
40
 
@@ -64,7 +67,7 @@ class CERNLDAPSyncPlugin:
64
67
  status, result, response, _ = self._connection.search(
65
68
  "OU=Users,OU=Organic Units,DC=cern,DC=ch",
66
69
  f"(CN={commonName})",
67
- attributes=["cernAccountOwner", "cernAccountType"],
70
+ attributes=["cernAccountOwner", "cernAccountType", "employeeId"],
68
71
  )
69
72
  if not status:
70
73
  raise ValueError(f"Bad status from LDAP search: {result}")
@@ -200,6 +200,7 @@ class ServiceReactor:
200
200
  services at the same time
201
201
  """
202
202
  sel = self.__getListeningSelector(svcName)
203
+ throttleExpires = None
203
204
  while self.__alive:
204
205
  clientTransport = None
205
206
  try:
@@ -223,12 +224,19 @@ class ServiceReactor:
223
224
  gLogger.warn(f"Client connected from banned ip {clientIP}")
224
225
  clientTransport.close()
225
226
  continue
227
+ # Handle throttling
228
+ if self.__services[svcName].wantsThrottle and throttleExpires is None:
229
+ throttleExpires = time.time() + THROTTLE_SERVICE_SLEEP_SECONDS
230
+ if throttleExpires:
231
+ if time.time() > throttleExpires:
232
+ throttleExpires = None
233
+ else:
234
+ gLogger.warn("Rejecting client due to throttling", str(clientTransport.getRemoteAddress()))
235
+ clientTransport.close()
236
+ continue
226
237
  # Handle connection
227
238
  self.__stats.connectionStablished()
228
239
  self.__services[svcName].handleConnection(clientTransport)
229
- while self.__services[svcName].wantsThrottle:
230
- gLogger.warn("Sleeping as service requested throttling", svcName)
231
- time.sleep(THROTTLE_SERVICE_SLEEP_SECONDS)
232
240
  # Renew context?
233
241
  now = time.time()
234
242
  renewed = False
@@ -40,7 +40,7 @@ from DIRAC.Core.Utilities.ReturnValues import convertToReturnValue, returnValueO
40
40
 
41
41
  PEM_BEGIN = "-----BEGIN DIRACX-----"
42
42
  PEM_END = "-----END DIRACX-----"
43
- RE_DIRACX_PEM = re.compile(rf"{PEM_BEGIN}\n(.*)\n{PEM_END}", re.MULTILINE | re.DOTALL)
43
+ RE_DIRACX_PEM = re.compile(rf"{PEM_BEGIN}\n(.*?)\n{PEM_END}", re.DOTALL)
44
44
 
45
45
 
46
46
  @convertToReturnValue
@@ -62,21 +62,26 @@ def addTokenToPEM(pemPath, group):
62
62
  token_type=token_content.get("token_type"),
63
63
  refresh_token=token_content.get("refresh_token"),
64
64
  )
65
-
66
65
  token_pem = f"{PEM_BEGIN}\n"
67
66
  data = base64.b64encode(serialize_credentials(token).encode("utf-8")).decode()
68
67
  token_pem += textwrap.fill(data, width=64)
69
68
  token_pem += f"\n{PEM_END}\n"
70
69
 
71
- with open(pemPath, "a") as f:
72
- f.write(token_pem)
70
+ pem = Path(pemPath).read_text()
71
+ # Remove any existing DiracX token there would be
72
+ new_pem = re.sub(RE_DIRACX_PEM, "", pem)
73
+ new_pem += token_pem
74
+
75
+ Path(pemPath).write_text(new_pem)
73
76
 
74
77
 
75
78
  def diracxTokenFromPEM(pemPath) -> dict[str, Any] | None:
76
79
  """Extract the DiracX token from the proxy PEM file"""
77
80
  pem = Path(pemPath).read_text()
78
- if match := RE_DIRACX_PEM.search(pem):
79
- match = match.group(1)
81
+ if match := RE_DIRACX_PEM.findall(pem):
82
+ if len(match) > 1:
83
+ raise ValueError("Found multiple DiracX tokens, this should never happen")
84
+ match = match[0]
80
85
  return json.loads(base64.b64decode(match).decode("utf-8"))
81
86
 
82
87
 
@@ -0,0 +1,161 @@
1
+ import base64
2
+ import json
3
+ import pytest
4
+ import tempfile
5
+ from pathlib import Path
6
+ from unittest.mock import patch, mock_open
7
+
8
+ from DIRAC.Core.Security.DiracX import diracxTokenFromPEM, PEM_BEGIN, PEM_END, RE_DIRACX_PEM
9
+
10
+
11
+ class TestDiracxTokenFromPEM:
12
+ """Test cases for diracxTokenFromPEM function"""
13
+
14
+ def create_valid_token_data(self):
15
+ """Create valid token data for testing"""
16
+ return {
17
+ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.test",
18
+ "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.refresh",
19
+ "expires_in": 3600,
20
+ "token_type": "Bearer",
21
+ }
22
+
23
+ def create_pem_content(self, token_data=None, include_other_content=True):
24
+ """Create PEM content with embedded DiracX token"""
25
+ if token_data is None:
26
+ token_data = self.create_valid_token_data()
27
+
28
+ # Encode token data
29
+ token_json = json.dumps(token_data)
30
+ encoded_token = base64.b64encode(token_json.encode("utf-8")).decode()
31
+
32
+ # Create PEM content
33
+ pem_content = ""
34
+ if include_other_content:
35
+ pem_content += "-----BEGIN CERTIFICATE-----\n"
36
+ pem_content += "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...\n"
37
+ pem_content += "-----END CERTIFICATE-----\n"
38
+
39
+ pem_content += f"{PEM_BEGIN}\n"
40
+ pem_content += encoded_token + "\n"
41
+ pem_content += f"{PEM_END}\n"
42
+
43
+ return pem_content
44
+
45
+ def test_valid_token_extraction(self):
46
+ """Test successful extraction of valid token from PEM file"""
47
+ token_data = self.create_valid_token_data()
48
+ pem_content = self.create_pem_content(token_data)
49
+
50
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".pem") as f:
51
+ f.write(pem_content)
52
+ temp_path = f.name
53
+
54
+ try:
55
+ result = diracxTokenFromPEM(temp_path)
56
+ assert result == token_data
57
+ finally:
58
+ Path(temp_path).unlink()
59
+
60
+ def test_no_token_in_pem(self):
61
+ """Test behavior when no DiracX token is present in PEM file"""
62
+ pem_content = """-----BEGIN CERTIFICATE-----
63
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
64
+ -----END CERTIFICATE-----"""
65
+
66
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".pem") as f:
67
+ f.write(pem_content)
68
+ temp_path = f.name
69
+
70
+ try:
71
+ result = diracxTokenFromPEM(temp_path)
72
+ assert result is None
73
+ finally:
74
+ Path(temp_path).unlink()
75
+
76
+ def test_multiple_tokens_error(self):
77
+ """Test that multiple tokens raise ValueError"""
78
+ token_data = self.create_valid_token_data()
79
+
80
+ # Create PEM with two tokens
81
+ pem_content = self.create_pem_content(token_data)
82
+ pem_content += "\n" + self.create_pem_content(token_data, include_other_content=False)
83
+
84
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".pem") as f:
85
+ f.write(pem_content)
86
+ temp_path = f.name
87
+
88
+ try:
89
+ with pytest.raises(ValueError, match="Found multiple DiracX tokens"):
90
+ diracxTokenFromPEM(temp_path)
91
+ finally:
92
+ Path(temp_path).unlink()
93
+
94
+ def test_malformed_base64(self):
95
+ """Test behavior with malformed base64 data"""
96
+ pem_content = f"""{PEM_BEGIN}
97
+ invalid_base64_data_that_will_cause_error!
98
+ {PEM_END}"""
99
+
100
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".pem") as f:
101
+ f.write(pem_content)
102
+ temp_path = f.name
103
+
104
+ try:
105
+ with pytest.raises(Exception): # base64.b64decode will raise an exception
106
+ diracxTokenFromPEM(temp_path)
107
+ finally:
108
+ Path(temp_path).unlink()
109
+
110
+ def test_invalid_json_in_token(self):
111
+ """Test behavior with invalid JSON in token data"""
112
+ invalid_json = "this is not valid json"
113
+ encoded_invalid = base64.b64encode(invalid_json.encode("utf-8")).decode()
114
+
115
+ pem_content = f"""{PEM_BEGIN}
116
+ {encoded_invalid}
117
+ {PEM_END}"""
118
+
119
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".pem") as f:
120
+ f.write(pem_content)
121
+ temp_path = f.name
122
+
123
+ try:
124
+ with pytest.raises(json.JSONDecodeError):
125
+ diracxTokenFromPEM(temp_path)
126
+ finally:
127
+ Path(temp_path).unlink()
128
+
129
+ def test_token_with_unicode_characters(self):
130
+ """Test token with unicode characters"""
131
+ unicode_token = {
132
+ "access_token": "token_with_unicode_ñ_é_ü",
133
+ "refresh_token": "refresh_with_emoji_🚀_🎉",
134
+ "expires_in": 3600,
135
+ "token_type": "Bearer",
136
+ }
137
+
138
+ pem_content = self.create_pem_content(unicode_token)
139
+
140
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".pem") as f:
141
+ f.write(pem_content)
142
+ temp_path = f.name
143
+
144
+ try:
145
+ result = diracxTokenFromPEM(temp_path)
146
+ assert result == unicode_token
147
+ finally:
148
+ Path(temp_path).unlink()
149
+
150
+ def test_regex_pattern_validation(self):
151
+ """Test that the regex pattern correctly identifies DiracX tokens"""
152
+ # Test that the regex matches the expected pattern
153
+ token_data = self.create_valid_token_data()
154
+ token_json = json.dumps(token_data)
155
+ encoded_token = base64.b64encode(token_json.encode("utf-8")).decode()
156
+
157
+ test_content = f"{PEM_BEGIN}\n{encoded_token}\n{PEM_END}"
158
+ matches = RE_DIRACX_PEM.findall(test_content)
159
+
160
+ assert len(matches) == 1
161
+ assert matches[0] == encoded_token
@@ -73,7 +73,7 @@ class TornadoService(BaseRequestHandler): # pylint: disable=abstract-method
73
73
  :py:class:`BaseRequestHandler <DIRAC.Core.Tornado.Server.private.BaseRequestHandler.BaseRequestHandler>` for more details.
74
74
 
75
75
  In order to pass information around and keep some states, we use instance attributes.
76
- These are initialized in the :py:meth:`.initialize` method.
76
+ These are initialized in the ``initialize`` methods.
77
77
 
78
78
  The handler only define the ``post`` verb. Please refer to :py:meth:`.post` for the details.
79
79
 
@@ -29,50 +29,50 @@ def test_base():
29
29
  time.sleep(1)
30
30
  p = Profiler(mainProcess.pid)
31
31
  res = p.pid()
32
- assert res["OK"] is True
32
+ assert res["OK"] is True, res
33
33
  res = p.status()
34
- assert res["OK"] is True
34
+ assert res["OK"] is True, res
35
35
  res = p.runningTime()
36
- assert res["OK"] is True
36
+ assert res["OK"] is True, res
37
37
  assert res["Value"] > 0
38
38
 
39
39
  res = p.memoryUsage()
40
- assert res["OK"] is True
40
+ assert res["OK"] is True, res
41
41
  assert res["Value"] > 0
42
42
  resWC = p.memoryUsage(withChildren=True)
43
- assert resWC["OK"] is True
43
+ assert resWC["OK"] is True, res
44
44
  assert resWC["Value"] > 0
45
45
  assert resWC["Value"] >= res["Value"]
46
46
 
47
47
  res = p.vSizeUsage()
48
- assert res["OK"] is True
48
+ assert res["OK"] is True, res
49
49
  assert res["Value"] > 0
50
50
  resWC = p.vSizeUsage(withChildren=True)
51
- assert resWC["OK"] is True
51
+ assert resWC["OK"] is True, res
52
52
  assert resWC["Value"] > 0
53
53
  assert resWC["Value"] >= res["Value"]
54
54
 
55
55
  res = p.vSizeUsage()
56
- assert res["OK"] is True
56
+ assert res["OK"] is True, res
57
57
  assert res["Value"] > 0
58
58
  resWC = p.vSizeUsage(withChildren=True)
59
- assert resWC["OK"] is True
59
+ assert resWC["OK"] is True, res
60
60
  assert resWC["Value"] > 0
61
61
  assert resWC["Value"] >= res["Value"]
62
62
 
63
63
  res = p.numThreads()
64
- assert res["OK"] is True
64
+ assert res["OK"] is True, res
65
65
  assert res["Value"] > 0
66
66
  resWC = p.numThreads(withChildren=True)
67
- assert resWC["OK"] is True
67
+ assert resWC["OK"] is True, res
68
68
  assert resWC["Value"] > 0
69
69
  assert resWC["Value"] >= res["Value"]
70
70
 
71
71
  res = p.cpuPercentage()
72
- assert res["OK"] is True
72
+ assert res["OK"] is True, res
73
73
  assert res["Value"] >= 0
74
74
  resWC = p.cpuPercentage(withChildren=True)
75
- assert resWC["OK"] is True
75
+ assert resWC["OK"] is True, res
76
76
  assert resWC["Value"] >= 0
77
77
  assert resWC["Value"] >= res["Value"]
78
78
 
@@ -88,13 +88,13 @@ def test_cpuUsage():
88
88
  time.sleep(2)
89
89
  p = Profiler(mainProcess.pid)
90
90
  res = p.pid()
91
- assert res["OK"] is True
91
+ assert res["OK"] is True, res
92
92
  res = p.status()
93
- assert res["OK"] is True
93
+ assert res["OK"] is True, res
94
94
 
95
95
  # user
96
96
  res = p.cpuUsageUser()
97
- assert res["OK"] is True
97
+ assert res["OK"] is True, res
98
98
  assert res["Value"] > 0
99
99
  resC = p.cpuUsageUser(withChildren=True)
100
100
  assert resC["OK"] is True
@@ -102,7 +102,7 @@ def test_cpuUsage():
102
102
  assert resC["Value"] >= res["Value"]
103
103
 
104
104
  res = p.cpuUsageUser()
105
- assert res["OK"] is True
105
+ assert res["OK"] is True, res
106
106
  assert res["Value"] > 0
107
107
  resC = p.cpuUsageUser(withChildren=True)
108
108
  assert resC["OK"] is True
@@ -121,15 +121,15 @@ def test_cpuUsage():
121
121
 
122
122
  # system
123
123
  res = p.cpuUsageSystem()
124
- assert res["OK"] is True
124
+ assert res["OK"] is True, res
125
125
  assert res["Value"] >= 0
126
126
  resWC = p.cpuUsageSystem(withChildren=True)
127
- assert resWC["OK"] is True
127
+ assert resWC["OK"] is True, res
128
128
  assert resWC["Value"] >= 0
129
129
  assert resWC["Value"] >= res["Value"]
130
130
 
131
131
  res = p.cpuUsageSystem()
132
- assert res["OK"] is True
132
+ assert res["OK"] is True, res
133
133
  assert res["Value"] > 0
134
134
  resC = p.cpuUsageSystem(withChildren=True)
135
135
  assert resC["OK"] is True
@@ -601,13 +601,13 @@ class ProxyDB(DB):
601
601
  :return: S_OK(dict)/S_ERROR() -- dict contain attribute and VOMS VO
602
602
  """
603
603
  if requiredVOMSAttribute:
604
- return S_OK({"attribute": requiredVOMSAttribute, "VOMSVO": Registry.getVOMSVOForGroup(userGroup)})
604
+ return S_OK({"attribute": requiredVOMSAttribute, "VO": Registry.getVOForGroup(userGroup)})
605
605
 
606
606
  csVOMSMapping = Registry.getVOMSAttributeForGroup(userGroup)
607
607
  if not csVOMSMapping:
608
608
  return S_ERROR(f"No mapping defined for group {userGroup} in the CS")
609
609
 
610
- return S_OK({"attribute": csVOMSMapping, "VOMSVO": Registry.getVOMSVOForGroup(userGroup)})
610
+ return S_OK({"attribute": csVOMSMapping, "VO": Registry.getVOForGroup(userGroup)})
611
611
 
612
612
  def getVOMSProxy(self, userDN, userGroup, requiredLifeTime=None, requestedVOMSAttr=None):
613
613
  """Get proxy string from the Proxy Repository for use with userDN
@@ -624,7 +624,7 @@ class ProxyDB(DB):
624
624
  if not retVal["OK"]:
625
625
  return retVal
626
626
  vomsAttr = retVal["Value"]["attribute"]
627
- vomsVO = retVal["Value"]["VOMSVO"]
627
+ vomsVO = retVal["Value"]["VO"]
628
628
 
629
629
  # Look in the cache
630
630
  retVal = self.__getPemAndTimeLeft(userDN, userGroup, vomsAttr)
@@ -38,8 +38,8 @@ Script.disableCS()
38
38
  from DIRAC.ConfigurationSystem.Client.Helpers.Registry import (
39
39
  findDefaultGroupForDN,
40
40
  getGroupOption,
41
+ getVOForGroup,
41
42
  getVOMSAttributeForGroup,
42
- getVOMSVOForGroup,
43
43
  )
44
44
  from DIRAC.FrameworkSystem.Client.ProxyManagerClient import gProxyManager
45
45
  from DIRAC.FrameworkSystem.private.authorization.utils.Tokens import (
@@ -285,7 +285,7 @@ class Params:
285
285
  if not (vomsAttr := getVOMSAttributeForGroup(self.group)):
286
286
  print(HTML(f"<yellow>No VOMS attribute foud for {self.group}</yellow>"))
287
287
  else:
288
- vo = getVOMSVOForGroup(self.group)
288
+ vo = getVOForGroup(self.group)
289
289
  if not (result := VOMS().setVOMSAttributes(self.outputFile, attribute=vomsAttr, vo=vo))["OK"]:
290
290
  return S_ERROR(f"Failed adding VOMS attribute: {result['Message']}")
291
291
  chain = result["Value"]
@@ -96,7 +96,7 @@ class ProxyInit:
96
96
  )
97
97
 
98
98
  resultVomsAttributes = VOMS.VOMS().setVOMSAttributes(
99
- self.__proxyGenerated, attribute=vomsAttr, vo=Registry.getVOMSVOForGroup(self.__piParams.diracGroup)
99
+ self.__proxyGenerated, attribute=vomsAttr, vo=Registry.getVOForGroup(self.__piParams.diracGroup)
100
100
  )
101
101
  if not resultVomsAttributes["OK"]:
102
102
  return S_ERROR(
@@ -5,8 +5,7 @@ Wrapper on top of ElasticDB. It is used to manage the DIRAC monitoring types.
5
5
 
6
6
  The following option can be set in `Systems/Monitoring/Databases/MonitoringDB`
7
7
 
8
- * *IndexPrefix*: Prefix used to prepend to indexes created in the ES instance. If this
9
- is not present in the CS, the indexes are prefixed with the setup name.
8
+ * *IndexPrefix*: Prefix used to prepend to indexes created in the OpenSearch instance.
10
9
 
11
10
  For each monitoring types managed, the Period (how often a new index is created)
12
11
  can be defined with::
@@ -33,7 +32,6 @@ import time
33
32
 
34
33
  from DIRAC import S_ERROR, S_OK
35
34
  from DIRAC.ConfigurationSystem.Client.Config import gConfig
36
- from DIRAC.ConfigurationSystem.Client.Helpers import CSGlobals
37
35
  from DIRAC.ConfigurationSystem.Client.PathFinder import getDatabaseSection
38
36
  from DIRAC.Core.Base.ElasticDB import ElasticDB
39
37
  from DIRAC.Core.Utilities.Plotting.TypeLoader import TypeLoader
@@ -48,7 +46,7 @@ class MonitoringDB(ElasticDB):
48
46
 
49
47
  try:
50
48
  section = getDatabaseSection("Monitoring/MonitoringDB")
51
- indexPrefix = gConfig.getValue(f"{section}/IndexPrefix", CSGlobals.getSetup()).lower()
49
+ indexPrefix = gConfig.getValue(f"{section}/IndexPrefix", "").lower()
52
50
  # Connecting to the ES cluster
53
51
  super().__init__(fullName=name, indexPrefix=indexPrefix)
54
52
  except RuntimeError as ex:
@@ -192,7 +190,10 @@ class MonitoringDB(ElasticDB):
192
190
  # and now we group with bucket aggregation
193
191
  groupingAggregation = self._A("terms", field=grouping, size=self.RESULT_SIZE)
194
192
  groupingAggregation.bucket(
195
- "end_data", "date_histogram", field="timestamp", interval=interval # name # type
193
+ "end_data",
194
+ "date_histogram",
195
+ field="timestamp",
196
+ interval=interval,
196
197
  ).metric("timeAggregation", timeAggregation).pipeline(
197
198
  "timeAggregation_avg_bucket", "avg_bucket", buckets_path="timeAggregation>total", gap_policy="insert_zeros"
198
199
  )
@@ -28,19 +28,29 @@ class WebAppHandler(RequestHandler):
28
28
  result = ObjectLoader().loadObject("WorkloadManagementSystem.DB.PilotAgentsDB", "PilotAgentsDB")
29
29
  if not result["OK"]:
30
30
  return result
31
- cls.pilotAgentsDB = result["Value"](parentLogger=cls.log)
31
+ try:
32
+ cls.pilotAgentsDB = result["Value"](parentLogger=cls.log)
33
+ except RuntimeError:
34
+ cls.log.warn("Could not connect to PilotAgentsDB")
32
35
 
33
36
  result = ObjectLoader().loadObject("WorkloadManagementSystem.DB.JobDB", "JobDB")
34
37
  if not result["OK"]:
35
38
  return result
36
- cls.jobDB = result["Value"](parentLogger=cls.log)
39
+ try:
40
+ cls.jobDB = result["Value"](parentLogger=cls.log)
41
+ except RuntimeError:
42
+ cls.log.warn("Could not connect to JobDB")
37
43
 
38
44
  result = ObjectLoader().loadObject("TransformationSystem.DB.TransformationDB", "TransformationDB")
39
45
  if not result["OK"]:
40
46
  return result
41
- cls.transformationDB = result["Value"](parentLogger=cls.log)
47
+ try:
48
+ cls.transformationDB = result["Value"](parentLogger=cls.log)
49
+ except RuntimeError:
50
+ cls.log.warn("Could not connect to TransformationDB")
42
51
 
43
52
  except RuntimeError as excp:
53
+ cls.log.exception()
44
54
  return S_ERROR(f"Can't connect to DB: {excp}")
45
55
 
46
56
  return S_OK()
@@ -5,7 +5,6 @@ import hashlib
5
5
  import re
6
6
 
7
7
  from DIRAC import S_OK, S_ERROR, gConfig
8
- from DIRAC.ConfigurationSystem.Client.Helpers import CSGlobals
9
8
  from DIRAC.ConfigurationSystem.Client.PathFinder import getServiceSection
10
9
  from DIRAC.MonitoringSystem.private.Plotters.BasePlotter import BasePlotter as myBasePlotter
11
10
  from DIRAC.Core.Utilities.ObjectLoader import loadObjects
@@ -56,7 +55,6 @@ class MainReporter:
56
55
  :param str setup: DIRAC setup
57
56
  """
58
57
  self.__db = db
59
- self.__setup = CSGlobals.getSetup().lower()
60
58
  self.__csSection = getServiceSection("Monitoring/Monitoring")
61
59
  self.__plotterList = PlottersList()
62
60
 
@@ -75,7 +73,6 @@ class MainReporter:
75
73
  requestToHash[key] = epoch - epoch % granularity
76
74
  md5Hash = hashlib.md5()
77
75
  md5Hash.update(repr(requestToHash).encode())
78
- md5Hash.update(self.__setup.encode())
79
76
  return md5Hash.hexdigest()
80
77
 
81
78
  def generate(self, reportRequest):
@@ -26,3 +26,16 @@ class CheckInIdProvider(OAuth2IdProvider):
26
26
 
27
27
  idPScope = f"eduperson_entitlement?value=urn:mace:egi.eu:group:{vo}:role={groupElements[1]}#aai.egi.eu"
28
28
  return scope_to_list(idPScope)
29
+
30
+ def fetchToken(self, **kwargs):
31
+ """Fetch token
32
+
33
+ :param kwargs:
34
+ :return: dict
35
+ """
36
+
37
+ if "audience" in kwargs:
38
+ kwargs["resource"] = kwargs["audience"]
39
+ kwargs.pop("audience")
40
+
41
+ return super().fetchToken(**kwargs)
@@ -1,10 +1,10 @@
1
1
  """
2
2
  Command Line Parameters for creating the Replication transformations Script
3
3
  """
4
- from DIRAC import S_OK, S_ERROR, gLogger
4
+ from DIRAC import S_ERROR, S_OK, gLogger
5
+ from DIRAC.ConfigurationSystem.Client.Helpers.Registry import getVOForGroup
5
6
  from DIRAC.Core.Security.Properties import SecurityProperty
6
7
  from DIRAC.Core.Security.ProxyInfo import getProxyInfo
7
- from DIRAC.ConfigurationSystem.Client.Helpers.Registry import getVOMSVOForGroup
8
8
 
9
9
 
10
10
  class Params:
@@ -144,7 +144,7 @@ class Params:
144
144
  return False
145
145
  proxyValues = proxyInfo.get("Value", {})
146
146
  group = proxyValues.get("group", "")
147
- vomsvo = getVOMSVOForGroup(group)
147
+ vomsvo = getVOForGroup(group)
148
148
  if not vomsvo:
149
149
  self.errorMessages.append("ERROR: ProxyGroup not associated to VOMS VO, get a different proxy")
150
150
  return False
@@ -16,7 +16,7 @@ from urllib.request import urlopen
16
16
  from DIRAC.Interfaces.API.Dirac import Dirac
17
17
  from DIRAC.Core.Utilities.File import mkDir
18
18
  from DIRAC.Core.Base.Script import Script
19
- from DIRAC.ConfigurationSystem.Client.Helpers.CSGlobals import getVO, getSetup
19
+ from DIRAC.ConfigurationSystem.Client.Helpers.CSGlobals import getVO
20
20
  from DIRAC.ConfigurationSystem.Client.ConfigurationData import gConfigurationData
21
21
 
22
22
 
@@ -79,14 +79,12 @@ def __configurePilot(basepath, vo):
79
79
  This method was created specifically for LHCb pilots, more info
80
80
  about othe VOs is needed to make it more general.
81
81
  """
82
- currentSetup = getSetup()
83
82
  masterCS = gConfigurationData.getMasterServer()
84
83
 
85
84
  os.system(
86
85
  "python "
87
86
  + basepath
88
- + "dirac-pilot.py -S %s -l %s -C %s -N ce.debug.ch -Q default -n DIRAC.JobDebugger.ch -dd"
89
- % (currentSetup, vo, masterCS)
87
+ + f"dirac-pilot.py -l {vo} -C {masterCS} -N ce.debug.ch -Q default -n DIRAC.JobDebugger.ch -dd"
90
88
  )
91
89
 
92
90
  diracdir = os.path.expanduser("~") + os.path.sep
@@ -1,14 +1,13 @@
1
1
  """Test the dirac-transformation-replication script and helper"""
2
2
  import unittest
3
+ from unittest.mock import MagicMock as Mock
4
+ from unittest.mock import patch
3
5
 
4
- from unittest.mock import MagicMock as Mock, patch
5
-
6
- from DIRAC import S_OK, S_ERROR
7
-
8
- from DIRAC.TransformationSystem.Utilities.ReplicationTransformation import createDataTransformation
6
+ from DIRAC import S_ERROR, S_OK
9
7
  from DIRAC.TransformationSystem.Utilities.ReplicationCLIParameters import Params
8
+ from DIRAC.TransformationSystem.Utilities.ReplicationTransformation import createDataTransformation
10
9
 
11
- GET_VOMS = "DIRAC.TransformationSystem.Utilities.ReplicationCLIParameters.getVOMSVOForGroup"
10
+ GET_VOMS = "DIRAC.TransformationSystem.Utilities.ReplicationCLIParameters.getVOForGroup"
12
11
  GET_PROXY = "DIRAC.TransformationSystem.Utilities.ReplicationCLIParameters.getProxyInfo"
13
12
 
14
13
 
@@ -229,12 +229,8 @@ class SiteDirector(AgentModule):
229
229
  site = self.queueDict[queueName]["Site"]
230
230
  ce = self.queueDict[queueName]["CEName"]
231
231
 
232
- # Check the status of the Site
233
- if site in siteMaskList:
234
- continue
235
-
236
- # Check the status of the CE (only for RSS=Active)
237
- if ce not in ceMaskList:
232
+ # Check the status of the Site and CE
233
+ if site in siteMaskList and ce in ceMaskList:
238
234
  continue
239
235
 
240
236
  self.log.warn("Queue not considered because not usable:", queueName)
@@ -169,10 +169,16 @@ def sd(mocker, config):
169
169
  gConfig.getSections("Resources/Sites/LCG")["Value"] + gConfig.getSections("Resources/Sites/DIRAC")["Value"]
170
170
  )
171
171
  mocker.patch(
172
- "DIRAC.WorkloadManagementSystem.Agent.SiteDirector.SiteStatus.getUsableSites", return_values=usableSites
172
+ "DIRAC.WorkloadManagementSystem.Agent.SiteDirector.SiteStatus.getUsableSites", return_value=S_OK(usableSites)
173
173
  )
174
+
175
+ # Mock getElementStatus to return a properly formatted dictionary
176
+ def mock_getElementStatus(ceNamesList, *args, **kwargs):
177
+ return S_OK({ceName: {"all": "Active"} for ceName in ceNamesList})
178
+
174
179
  mocker.patch(
175
- "DIRAC.WorkloadManagementSystem.Agent.SiteDirector.ResourceStatus.getElementStatus", return_values=usableSites
180
+ "DIRAC.WorkloadManagementSystem.Agent.SiteDirector.ResourceStatus.getElementStatus",
181
+ side_effect=mock_getElementStatus,
176
182
  )
177
183
  mocker.patch(
178
184
  "DIRAC.WorkloadManagementSystem.Agent.SiteDirector.gProxyManager.downloadProxy", side_effect=mockPMProxyReply
@@ -1,10 +1,10 @@
1
- """ Module containing a front-end to the OpenSearch-based JobParametersDB.
2
- This is a drop-in replacement for MySQL-based table JobDB.JobParameters.
1
+ """Module containing a front-end to the OpenSearch-based JobParametersDB.
2
+ This is a drop-in replacement for MySQL-based table JobDB.JobParameters.
3
3
 
4
- The following class methods are provided for public usage
5
- - getJobParameters()
6
- - setJobParameter()
7
- - deleteJobParameters()
4
+ The following class methods are provided for public usage
5
+ - getJobParameters()
6
+ - setJobParameter()
7
+ - deleteJobParameters()
8
8
  """
9
9
 
10
10
  from DIRAC import S_ERROR, S_OK
@@ -37,11 +37,11 @@ class JobParametersDB(ElasticDB):
37
37
  def __init__(self, parentLogger=None):
38
38
  """Standard Constructor"""
39
39
 
40
- self.fullname = "WorkloadManagement/ElasticJobParametersDB"
40
+ self.fullname = "WorkloadManagement/JobParametersDB"
41
41
  self.index_name = self.getCSOption("index_name", "job_parameters")
42
42
 
43
43
  try:
44
- # Connecting to the ES cluster
44
+ # Connecting to the OpenSearch cluster
45
45
  super().__init__(self.fullname, self.index_name, parentLogger=parentLogger)
46
46
  except Exception:
47
47
  RuntimeError("Can't connect to JobParameters index")
@@ -64,7 +64,7 @@ class SandboxMetadataDB(DB):
64
64
  "Type": "VARCHAR(64) NOT NULL",
65
65
  },
66
66
  "Indexes": {"Entity": ["EntityId"], "SBIndex": ["SBId"]},
67
- "UniqueIndexes": {"Mapping": ["SBId", "EntityId", "Type"]},
67
+ "PrimaryKey": ["SBId", "EntityId", "Type"],
68
68
  }
69
69
 
70
70
  for tableName in self.__tablesDesc:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DIRAC
3
- Version: 9.0.1
3
+ Version: 9.0.4
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,9 +19,10 @@ Requires-Dist: cachetools
19
19
  Requires-Dist: certifi
20
20
  Requires-Dist: cwltool
21
21
  Requires-Dist: diraccfg
22
- Requires-Dist: DIRACCommon==v9.0.1
23
- Requires-Dist: diracx-client>=v0.0.1a18
24
- Requires-Dist: diracx-core>=v0.0.1a18
22
+ Requires-Dist: DIRACCommon==v9.0.4
23
+ Requires-Dist: diracx-client>=v0.0.1
24
+ Requires-Dist: diracx-core>=v0.0.1
25
+ Requires-Dist: diracx-cli>=v0.0.1
25
26
  Requires-Dist: db12
26
27
  Requires-Dist: fts3
27
28
  Requires-Dist: gfal2-python
@@ -40,7 +41,6 @@ Requires-Dist: python-dateutil
40
41
  Requires-Dist: pytz
41
42
  Requires-Dist: requests
42
43
  Requires-Dist: rucio-clients>=34.4.2
43
- Requires-Dist: setuptools
44
44
  Requires-Dist: sqlalchemy
45
45
  Requires-Dist: typing_extensions>=4.3.0
46
46
  Requires-Dist: Authlib>=1.0.0.a2
@@ -63,15 +63,15 @@ DIRAC/ConfigurationSystem/Client/PathFinder.py,sha256=wxOWC0_UznF7XJc0LP9DX8y3yl
63
63
  DIRAC/ConfigurationSystem/Client/Utilities.py,sha256=lQepoCgaAvg9GW3_-s-IXkWb3fN3HJJP95pYhNEC2_4,27200
64
64
  DIRAC/ConfigurationSystem/Client/VOMS2CSSynchronizer.py,sha256=7gcA6eqKIeRBLxETR5CjCdqXHZeQMVDNZfHkz28W20k,31433
65
65
  DIRAC/ConfigurationSystem/Client/__init__.py,sha256=Jkxofl9cI04MqJcu_ZP8Wdk3WXOmiESFJS9e81LnG2Y,52
66
- DIRAC/ConfigurationSystem/Client/Helpers/CSGlobals.py,sha256=_txOWvYqcRzK4n4VVEwvECe_B45PmqiYHTxjEIOP6MQ,1053
66
+ DIRAC/ConfigurationSystem/Client/Helpers/CSGlobals.py,sha256=taQyqusXtK3zAtoQY9tpCyHAr9jU7U7cjRDvW8YmUwk,911
67
67
  DIRAC/ConfigurationSystem/Client/Helpers/Operations.py,sha256=jrpeauEwV6_xXQwVEbs6DDboB8oUmzkZkB_Xg8ZgdBQ,5991
68
68
  DIRAC/ConfigurationSystem/Client/Helpers/Path.py,sha256=ghRMD2qNaKejwg4RZ3m4LzfCG5bg1afvTnwJQydl94w,930
69
- DIRAC/ConfigurationSystem/Client/Helpers/Registry.py,sha256=svibVaHyRKRKPEs-k4pXgcTzr74qe72m4jo2Ue9Xqts,20775
69
+ DIRAC/ConfigurationSystem/Client/Helpers/Registry.py,sha256=qHxZ1MXg29tOTS5KxId3jVJHRpHc35cttlIWsrSwiuk,20229
70
70
  DIRAC/ConfigurationSystem/Client/Helpers/Resources.py,sha256=g6ZRdAydAnyKHjL9Gh6VS-jP5zb64q7uMOohtn8rin8,15604
71
71
  DIRAC/ConfigurationSystem/Client/Helpers/ResourcesDefaults.py,sha256=m6s-ZvjtYcLGsuu6mkCpIzxA8rEUYnwOOw1HvjecuJQ,3314
72
72
  DIRAC/ConfigurationSystem/Client/Helpers/__init__.py,sha256=syOASwgkZHn6b6ybYYu15wO8mrZXj7T-gIHk3EDlpjc,206
73
73
  DIRAC/ConfigurationSystem/Client/Helpers/test/Test_Helpers.py,sha256=_pfEyd5tw5OGCluNWT8cN2PIX_XEr1gLZPHPXEG0zXs,5543
74
- DIRAC/ConfigurationSystem/Client/SyncPlugins/CERNLDAPSyncPlugin.py,sha256=p1gSEKMY85dMQvJST5oDQiUeeMedMCSUdXyRThE8hgo,3376
74
+ DIRAC/ConfigurationSystem/Client/SyncPlugins/CERNLDAPSyncPlugin.py,sha256=RuTjybzvD-ioxuDKHmOsyzMMZIAaJHqE5WOrHdMN8vE,3538
75
75
  DIRAC/ConfigurationSystem/Client/SyncPlugins/DummySyncPlugin.py,sha256=hGXcNMxh3r7sCXkTs5r1Mlvz6FjlZ1lBo9NzavQzoBo,1420
76
76
  DIRAC/ConfigurationSystem/Client/SyncPlugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
77
  DIRAC/ConfigurationSystem/Client/test/Test_LocalConfiguration.py,sha256=bGuaALxrvTYNo9eAYJzzL-q0FXgWdd6vguvGI1c4jA0,7432
@@ -121,7 +121,7 @@ DIRAC/Core/DISET/AuthManager.py,sha256=-aSXHK4Lxtr_jd4efVEL2xuqnsIaKHGyPNiq2H111
121
121
  DIRAC/Core/DISET/MessageClient.py,sha256=tOluMqcZmvM7wIQm0X957_lXNdlYpxST-LZitYbK9NQ,6007
122
122
  DIRAC/Core/DISET/RPCClient.py,sha256=Sg3wIpy_I0Z6x2w_hs1Z1qtBdiStkvEkESPtXuagno0,3816
123
123
  DIRAC/Core/DISET/RequestHandler.py,sha256=42NoL2_2lN_N7YIHSBWpPPBYtF2OQ4PLqxBX1ca3_Ys,24044
124
- DIRAC/Core/DISET/ServiceReactor.py,sha256=JU3cPaVvXVUtbkXm1KPje4T4Ksg1mH728FW_OWQnIS0,10923
124
+ DIRAC/Core/DISET/ServiceReactor.py,sha256=AVLKPkUY3IRoADVzMjLMXtOBhXKanPYHt5_k9e--ZBo,11281
125
125
  DIRAC/Core/DISET/ThreadConfig.py,sha256=Q43BnQ8yliFliU65rLxHBV49c4TFzrYq9Ewe5n2vASQ,3086
126
126
  DIRAC/Core/DISET/TransferClient.py,sha256=2WDH3Be5NSAY4xWRK0RL2OnKeQLtaPRIJLQeeVYY5V8,7657
127
127
  DIRAC/Core/DISET/__init__.py,sha256=ZPbhSIBCK14nC9R5drkX8lfK2YHY7g-WVg0Zuy3uHAc,1085
@@ -154,7 +154,7 @@ DIRAC/Core/LCG/GGUSTicketsClient.py,sha256=dlt9-cy2lptdiMa56YTV5g7uZrXaPIvbvTK-c
154
154
  DIRAC/Core/LCG/GOCDBClient.py,sha256=FTxnwJqd3j99vfLkC2ouyrCsnVLFEwg_GHaq6zY1Db8,15439
155
155
  DIRAC/Core/LCG/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
156
156
  DIRAC/Core/LCG/test/Test_LCG.py,sha256=2VsUEgyWDC6BC2KsMz9tB6TsMHYmpg0Qfjs3utiXKcg,32871
157
- DIRAC/Core/Security/DiracX.py,sha256=lMnqdhgONZYr96YHTwx8g0dwDgfejT5kJBicS4E3IWw,5022
157
+ DIRAC/Core/Security/DiracX.py,sha256=kpPQXYzL_dAf_q3xyBaEHgJS8fKUX3Uvv13GTlP_soI,5266
158
158
  DIRAC/Core/Security/IAMService.py,sha256=7LQs3PuDz1KM6r6rMefjiV_9FCpXL-sDUNm8-rrdGOE,6911
159
159
  DIRAC/Core/Security/Locations.py,sha256=Ew1-J4tAwfbgkW1_MAlIIkeBi6_MJLsefNAL8vBi7_k,8031
160
160
  DIRAC/Core/Security/Properties.py,sha256=CjHN-YQwBiAdZyTos9b6Zpg5a6Sh_hFNUvpszxzEgnE,6180
@@ -175,6 +175,7 @@ DIRAC/Core/Security/test/Test_X509Certificate.py,sha256=bN51zF-3SepZOcvfScP_-yS4
175
175
  DIRAC/Core/Security/test/Test_X509Chain.py,sha256=xGYmr_VgYeayf3JEqtauCXVt7INAR7FQj_hmZl8PRCw,18694
176
176
  DIRAC/Core/Security/test/Test_X509Request.py,sha256=Cl5fA8xGAiHsmEmGnA2KOriADnzPI1U878jxmw2b4vg,3258
177
177
  DIRAC/Core/Security/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
178
+ DIRAC/Core/Security/test/test_diracx_token_from_pem.py,sha256=EYh1WmJhPvsq8PvWbUTax2KPZNH2HAIjZQGq8EAPJiY,5632
178
179
  DIRAC/Core/Security/test/x509TestUtilities.py,sha256=pPZTJtVsLy77Xlqjadwcj5TSW30alFx_F7mWpuyKYYE,17234
179
180
  DIRAC/Core/Security/test/certs/ca/b236481c.0,sha256=ZShotyOrATnsvKDGbcWJAHfGfuO2ygyvEIeAmjqf0UI,1988
180
181
  DIRAC/Core/Security/test/certs/ca/ca.cert.pem,sha256=ZShotyOrATnsvKDGbcWJAHfGfuO2ygyvEIeAmjqf0UI,1988
@@ -211,7 +212,7 @@ DIRAC/Core/Tornado/Client/private/__init__.py,sha256=cO7z-h1lVEu7RRPYeY3BZLJu-FZ
211
212
  DIRAC/Core/Tornado/Server/HandlerManager.py,sha256=IQG2_dufNM43TGqfYU6QOTMlJyPdeCSs7TWqHlAls_Q,8181
212
213
  DIRAC/Core/Tornado/Server/TornadoREST.py,sha256=-4_gROsCYPrwHifagoZFqUSfu6mlkk4PMeL9G7NTba0,15884
213
214
  DIRAC/Core/Tornado/Server/TornadoServer.py,sha256=VAVtrk9zRdm4WiJDB-RhJ0sqmfmUBImZzJh4Cy_E5-o,11823
214
- DIRAC/Core/Tornado/Server/TornadoService.py,sha256=lqyUnLkQr7TCDUCfBxfdr9rJ-8DNF1mQqlcKV-7Nh9U,9022
215
+ DIRAC/Core/Tornado/Server/TornadoService.py,sha256=ej-5GrKjKi9BNN0VJICIt4NA0vS2Ig2nfQ880wMs10E,9015
215
216
  DIRAC/Core/Tornado/Server/__init__.py,sha256=cO7z-h1lVEu7RRPYeY3BZLJu-FZH9p7Gvuukw1ZgcME,31
216
217
  DIRAC/Core/Tornado/Server/private/BaseRequestHandler.py,sha256=WbNLdwa3Vz6x7CndZ-7BlHzN1VihFUdyWBOyuzrbXNQ,42813
217
218
  DIRAC/Core/Tornado/Server/private/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -301,7 +302,7 @@ DIRAC/Core/Utilities/test/Test_Network.py,sha256=n1m1OB9JIEqT4AGz_DKt9QOgMOsV6m5
301
302
  DIRAC/Core/Utilities/test/Test_ObjectLoader.py,sha256=PfDjfnPNNByC7Ropkfl8qrkjUWFJ702wRmH7_0_Qg9Q,968
302
303
  DIRAC/Core/Utilities/test/Test_Pfn.py,sha256=XWTXejQf_TnicaPbQ4ZyDsl1KXDpq3IMNFlQ2cM3140,7398
303
304
  DIRAC/Core/Utilities/test/Test_ProcessPool.py,sha256=NnfHNkhTOgADk-P9ds_ADuvcSNlK_XdoibRkk13r_NE,10890
304
- DIRAC/Core/Utilities/test/Test_Profiler.py,sha256=Y4h6GzIHJb0yvbNWYczj-GC5Ibx59ecEC4i1FLzlN-o,4115
305
+ DIRAC/Core/Utilities/test/Test_Profiler.py,sha256=8QRRXm-PwJpjLGwAOJxnrpnnMbmVzXhJ1ZcQ9gDBX5c,4215
305
306
  DIRAC/Core/Utilities/test/Test_ReturnValues.py,sha256=w6Jz-Vblgu8RDXPzVi6BZjuFXcSmW-Zb0mcBgW1RWOw,1926
306
307
  DIRAC/Core/Utilities/test/Test_Subprocess.py,sha256=nAiVF5oMnle-4E8ijlWF-ilBfgN2VGkkFQQSKhIKN2o,2141
307
308
  DIRAC/Core/Utilities/test/Test_entrypoints.py,sha256=z_3f7m59v3W6ZsqgeCFbJoBnMY-cKR_blKbPqcV7528,413
@@ -508,7 +509,7 @@ DIRAC/FrameworkSystem/DB/AuthDB.py,sha256=QLotpINMq45FNoFO2AV3OH5Ij5i__HHk-p-m-b
508
509
  DIRAC/FrameworkSystem/DB/AuthDB.sql,sha256=tcAnRmBBEDxljAXILp8tlLzuEb7vOoN190KQK7NSbQQ,95
509
510
  DIRAC/FrameworkSystem/DB/InstalledComponentsDB.py,sha256=rVarVs61K1kPHZIf1U_kfia-5pxR5uSXsuDutr8EcFY,43156
510
511
  DIRAC/FrameworkSystem/DB/InstalledComponentsDB.sql,sha256=-LFjjn1gRQo7zDOclKmFwmbZi_lXXnx_B17cZPLBUak,113
511
- DIRAC/FrameworkSystem/DB/ProxyDB.py,sha256=XH7uSohf1bO-M64BHF7MoG16zyht8sY_lsGgLE3clkU,39726
512
+ DIRAC/FrameworkSystem/DB/ProxyDB.py,sha256=5gnttlg9pJpyq9nYZDqEe_TihO6Ug3BImaHGcz0kjnQ,39706
512
513
  DIRAC/FrameworkSystem/DB/ProxyDB.sql,sha256=QwWe_mRX_NbZQVBo3TzA60L3FemI-oLY8G7_4uRFPzU,96
513
514
  DIRAC/FrameworkSystem/DB/TokenDB.py,sha256=FjHsPuTYt2KaXs0fST_tOAZyXY1R6417BB-lblxduZ4,8652
514
515
  DIRAC/FrameworkSystem/DB/TokenDB.sql,sha256=D-D78eFUkCRb4YLNZqdCfmyaEIJFupgMhIwgSs91yE4,96
@@ -579,12 +580,12 @@ DIRAC/FrameworkSystem/scripts/dirac_admin_update_pilot.py,sha256=sxrioz8QtnZfWoP
579
580
  DIRAC/FrameworkSystem/scripts/dirac_admin_users_with_proxy.py,sha256=qPvgY1cp8_QOOEuOyOQA6MIjvweheGTVCaS_OK7Yfa0,2549
580
581
  DIRAC/FrameworkSystem/scripts/dirac_diracx_whoami.py,sha256=Sj7ovgENBe5naW0U9VPgumEO6f1-kLElfhZnAvCX6fg,653
581
582
  DIRAC/FrameworkSystem/scripts/dirac_install_component.py,sha256=cjKWUspscXdKHA-GjwBv9jntEyp-gleFoYg456Y0XWQ,5159
582
- DIRAC/FrameworkSystem/scripts/dirac_login.py,sha256=ZwPikf4LFa72weKA627-V04hPSvZprb_s1glueJa1EQ,16119
583
+ DIRAC/FrameworkSystem/scripts/dirac_login.py,sha256=AAk4ulVmbdcCw8XGLKnlupDNa8m80ouSuGiyohn1W4A,16111
583
584
  DIRAC/FrameworkSystem/scripts/dirac_logout.py,sha256=9JqINw-Fqoxk1aH8LnRP_gF9DNADhv3zFar51DBBJ3w,3668
584
585
  DIRAC/FrameworkSystem/scripts/dirac_proxy_destroy.py,sha256=Db6Su17yuie2KX0vcXiqwa0BTmmU2x0_TB3vROiem-g,5009
585
586
  DIRAC/FrameworkSystem/scripts/dirac_proxy_get_uploaded_info.py,sha256=nCSGTZwOeg8kHF_Kp5OPs8Z6W1F3H7lw7aZcjVztr5E,3537
586
587
  DIRAC/FrameworkSystem/scripts/dirac_proxy_info.py,sha256=X7zQawo7ZCD4bpoUE1WR2vWExsH7V7OwcWINKSNmssM,6182
587
- DIRAC/FrameworkSystem/scripts/dirac_proxy_init.py,sha256=mIP5TAB42lxfq4TFNGhhxgHFz2fA1vSDfmc74TU42T0,10170
588
+ DIRAC/FrameworkSystem/scripts/dirac_proxy_init.py,sha256=effVCmzUUDoWOSak-e1dyb2haYPeWsMU_7ali51xgHE,10166
588
589
  DIRAC/FrameworkSystem/scripts/dirac_restart_component.py,sha256=U1FPMHYhJP0xQzfN88SshzXamB-lqanAhOzWQ7JSOuk,1275
589
590
  DIRAC/FrameworkSystem/scripts/dirac_start_component.py,sha256=nlCSTjG_w57t4W2vlV_22_stBa2HZfIXTOicSzfYXg0,1289
590
591
  DIRAC/FrameworkSystem/scripts/dirac_status_component.py,sha256=KbNYSyHLZueVNLBbFHNnl7MF5gWR2JTie13GH6tlIfQ,1658
@@ -694,15 +695,15 @@ DIRAC/MonitoringSystem/Client/Types/RMSMonitoring.py,sha256=DzmMIY22YKazfmfv8kOG
694
695
  DIRAC/MonitoringSystem/Client/Types/ServiceMonitoring.py,sha256=IZ_SIJbv8Eoub2DbbjKjSqlj0xNMU6wU9tX4EtOFU40,1491
695
696
  DIRAC/MonitoringSystem/Client/Types/WMSHistory.py,sha256=MHQ9tIJXoaX4lFPD4XivJRLO8Z1-QK28rzJf_IvNYKk,1488
696
697
  DIRAC/MonitoringSystem/Client/Types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
697
- DIRAC/MonitoringSystem/DB/MonitoringDB.py,sha256=XZm32V1QShRBIq4FsONuwGHFSArXSmyc8gWmyoBgk_M,19357
698
+ DIRAC/MonitoringSystem/DB/MonitoringDB.py,sha256=4PH3x12cF-uyc0eyVVom7zvuZFduVlN10nVxwvJfSyw,19207
698
699
  DIRAC/MonitoringSystem/DB/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
699
700
  DIRAC/MonitoringSystem/DB/test/Test_monitoringdb.py,sha256=Jf4NZgb9V6U4DYk4SCLVoTqxJVBYsj49rIaYB7e6qxw,2788
700
701
  DIRAC/MonitoringSystem/Service/MonitoringHandler.py,sha256=JGN1MUsxP8swTuIa4qdPvo-O4UoA6TkxjfDZ1sC6L2w,12332
701
702
  DIRAC/MonitoringSystem/Service/TornadoMonitoringHandler.py,sha256=06gIHrrLJTgI-vnCHAGsDDjZrRwJaMsa8ESsdWy0Ir8,1550
702
- DIRAC/MonitoringSystem/Service/WebAppHandler.py,sha256=MOy9ywTbRf20wn2Xh4HYHZ92vBhh6fnjqZE67f8mheE,22758
703
+ DIRAC/MonitoringSystem/Service/WebAppHandler.py,sha256=utTyM5L28jEli_ZNeg5S4-prT4c38aeJHDhgyI-Sr-4,23148
703
704
  DIRAC/MonitoringSystem/Service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
704
705
  DIRAC/MonitoringSystem/private/DBUtils.py,sha256=bBEJoy3KCaYi7tIAmNdCIUF5K5-oJAS3qJn0ngpo-HQ,7163
705
- DIRAC/MonitoringSystem/private/MainReporter.py,sha256=kSIN0Z4_oiBLCjFLsMIoZh8YbED24yRP3Y1G4MqOI14,3594
706
+ DIRAC/MonitoringSystem/private/MainReporter.py,sha256=a1yTBMA_wQIzohugtV_MXxiwV7Qo1e2bGrJQZFO93Go,3433
706
707
  DIRAC/MonitoringSystem/private/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
707
708
  DIRAC/MonitoringSystem/private/Plotters/BasePlotter.py,sha256=8r0CVv9XyzZ15H_1rwsMFhyMGcV_ZYc8ZmPcFCBqWFE,16710
708
709
  DIRAC/MonitoringSystem/private/Plotters/RMSMonitoringPlotter.py,sha256=16oVdQjGo2VcWr02ChG4rEZCsVxqsocHzdLyJpcA3i4,3123
@@ -945,7 +946,7 @@ DIRAC/Resources/Computing/test/Test_InProcessComputingElement.py,sha256=j_ESF_f7
945
946
  DIRAC/Resources/Computing/test/Test_PoolComputingElement.py,sha256=Vmil6Z9bazv_AKeenma7LznzJAdrUf2xKMQ6HP0PhLE,11860
946
947
  DIRAC/Resources/Computing/test/Test_SSHComputingElement.py,sha256=ahYUZ9hySaEXik3nvUMWJ7eP87xj6u-LMDpX7A1OQd4,2425
947
948
  DIRAC/Resources/Computing/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
948
- DIRAC/Resources/IdProvider/CheckInIdProvider.py,sha256=xMGhVQGGuiouxtuH4jJSsfqd53yk67p4oSNn_-gDft8,879
949
+ DIRAC/Resources/IdProvider/CheckInIdProvider.py,sha256=Tq8ENK6yhC7Tl6JkTF1q8mCOrFRfsN3ediF251iU4oM,1163
949
950
  DIRAC/Resources/IdProvider/IAMIdProvider.py,sha256=kk2ty2mLevxGmJRBpLYlQXce_vy4cxp-dO2w7b1rCz0,822
950
951
  DIRAC/Resources/IdProvider/IdProviderFactory.py,sha256=-MbDuQ7bIGcBhaHDAlA9NUzgC6VwMlujfHUOwf8uzEE,3899
951
952
  DIRAC/Resources/IdProvider/OAuth2IdProvider.py,sha256=smoGhSD1JsyjJDot9XmMUmT7fw8kcfS3w392s2Lg9P8,23650
@@ -1088,13 +1089,13 @@ DIRAC/TransformationSystem/Service/TornadoTransformationManagerHandler.py,sha256
1088
1089
  DIRAC/TransformationSystem/Service/TransformationManagerHandler.py,sha256=02CxUBq9WmCHt2kAeSDkyw1Ul5QfuOBuf-VJwPnYEpE,20438
1089
1090
  DIRAC/TransformationSystem/Service/__init__.py,sha256=u3bZshx_dmLaeAOV5QX5dohrupszf9SR5rHkVwk5XJw,51
1090
1091
  DIRAC/TransformationSystem/Utilities/JobInfo.py,sha256=sUJNj-_5iA59eRFSSWQCCLo8HQIoh7m1xmxXrpzb3MU,10706
1091
- DIRAC/TransformationSystem/Utilities/ReplicationCLIParameters.py,sha256=oGEnS96Tq6NnPyu79C0xIZCBEZTDCe_SNAAibkIdiJE,6387
1092
+ DIRAC/TransformationSystem/Utilities/ReplicationCLIParameters.py,sha256=RK9FTLzHicDnT60J-W6jLtxZaMh4OIxq5MltNjETv7Y,6379
1092
1093
  DIRAC/TransformationSystem/Utilities/ReplicationTransformation.py,sha256=RJIobUwK_g_gG5GjApeJ6zi2bff03fW7-fHVxqK3-ms,5064
1093
1094
  DIRAC/TransformationSystem/Utilities/ScriptUtilities.py,sha256=5HMW2uVoFVQyJGwxec-_hldEzucRHSzMOwSvdUUuHrM,2523
1094
1095
  DIRAC/TransformationSystem/Utilities/TransformationInfo.py,sha256=Y1k5JjkODJUZeLQuWaBqJUGK1bPm9flWQD6cn9F-Mf4,8629
1095
1096
  DIRAC/TransformationSystem/Utilities/__init__.py,sha256=CrAP4Orxp0lk-GXnu9Gm46BXDNbidViM7YT0FNn1rRo,37
1096
1097
  DIRAC/TransformationSystem/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1097
- DIRAC/TransformationSystem/scripts/dirac_production_runjoblocal.py,sha256=HWgzcD07Q30nSzKDKH5EnH24Uqmt9_XLcnLa7fsI9YY,4782
1098
+ DIRAC/TransformationSystem/scripts/dirac_production_runjoblocal.py,sha256=A8RnNV60icEWAPjuskMVU27pguzoXAz_VBUzmrUAr4o,4708
1098
1099
  DIRAC/TransformationSystem/scripts/dirac_transformation_add_files.py,sha256=hY7gaTvfRiNvT7zi1OG2hTFV36U0C5W3AWFcXmKMuhA,1553
1099
1100
  DIRAC/TransformationSystem/scripts/dirac_transformation_cli.py,sha256=qhLTZqbnZSrRai3J7102ZQUMJTNxJfSvdK1lb3BCnik,363
1100
1101
  DIRAC/TransformationSystem/scripts/dirac_transformation_get_files.py,sha256=bV_vPkeu42ScP-rGXEeBT8JcmZS9O2ZifbHwQsIHECA,802
@@ -1106,7 +1107,7 @@ DIRAC/TransformationSystem/scripts/dirac_transformation_verify_outputdata.py,sha
1106
1107
  DIRAC/TransformationSystem/test/Test_DRA.py,sha256=K7kqBljTtpFoq8Kr55EqI33KE_U98ONs34ggF-5y8wU,26861
1107
1108
  DIRAC/TransformationSystem/test/Test_JobInfo.py,sha256=OW12FLuD4Njz2gTTxeu-BHu_PHthVDQdoPY6_PWxHoM,25705
1108
1109
  DIRAC/TransformationSystem/test/Test_TransformationInfo.py,sha256=gSNiXhMzbvO9VmlEtcRQmbtgx3fTNS50zGgNq6CRsKE,15547
1109
- DIRAC/TransformationSystem/test/Test_replicationTransformation.py,sha256=dunRhego8R-exx-0wx-rTDvZ_KqzxXp5eMBsVUTzftg,10836
1110
+ DIRAC/TransformationSystem/test/Test_replicationTransformation.py,sha256=5SSUuYY0KtsbraWFrbM8uz3lGNnzSCfLZppqyNUwsLA,10855
1110
1111
  DIRAC/TransformationSystem/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1111
1112
  DIRAC/Workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1112
1113
  DIRAC/Workflow/Modules/FailoverRequest.py,sha256=QFv_YXtItXMzfGGKAIk_UJMSK1Maze3xEB4bQFLGq1U,3941
@@ -1125,7 +1126,7 @@ DIRAC/WorkloadManagementSystem/Agent/PilotLoggingAgent.py,sha256=ZIgvFpasGTh76GW
1125
1126
  DIRAC/WorkloadManagementSystem/Agent/PilotStatusAgent.py,sha256=qY6TbYCPOFFXhHffmRJLNEbWvZPyg5Lc5B_8BbyQ7zc,9711
1126
1127
  DIRAC/WorkloadManagementSystem/Agent/PilotSyncAgent.py,sha256=qzDFCGZ8EtjxDUaPgyFDlSmJfyF2KLuyXTC7au3-p2Q,4860
1127
1128
  DIRAC/WorkloadManagementSystem/Agent/PushJobAgent.py,sha256=IvHshnw2xN0AZrruEu86C47GDez8enBD6jjNIZd6QcA,38594
1128
- DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py,sha256=ZnbjKca8tWLekObALrsFXm7EoXAYxEpHSGRAbrqU5mk,45229
1129
+ DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py,sha256=NkAyYGtht9NO53CX9OmbxBkeUFcfv7tc9CKogD8TtVU,45131
1129
1130
  DIRAC/WorkloadManagementSystem/Agent/StalledJobAgent.py,sha256=foEbmRotEmfeQG6nyIsJv1kSJkm4flkQsPYbSylS3SM,24572
1130
1131
  DIRAC/WorkloadManagementSystem/Agent/StatesAccountingAgent.py,sha256=iNIlWQEDBk6R1S8oHOIusZUwxOwLtgwuzR_4s32-o5w,8707
1131
1132
  DIRAC/WorkloadManagementSystem/Agent/TaskQueuesAgent.py,sha256=ypsmo233TFXq9IC5uz6pum7_joOh2gFPUYNmmCpukAY,943
@@ -1135,7 +1136,7 @@ DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobCleaningAgent.py,sha256=
1135
1136
  DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PilotLoggingAgent.py,sha256=KpvaqAaTaCXUpbdBpA_n7At3284XKYwx8GpC3Ah7cHg,8611
1136
1137
  DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PilotStatusAgent.py,sha256=qOA_U2NYvJprLdrUJirbEVSnvEF9-FuRXNi78MBoffc,2806
1137
1138
  DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PushJobAgent.py,sha256=Uf5jlnw8mWvQJcOnJXEASEf3Ryo63wZKv8IavQVaOVY,14887
1138
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_SiteDirector.py,sha256=ynC8NJobwWCRzKAKnQi2qhnPzwQypZRzBrwKGtUmmhs,11440
1139
+ DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_SiteDirector.py,sha256=o6imUULkKrvbmkfpvER8wyg0Ncn3gxvJNTNO8xKX7_w,11670
1139
1140
  DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_StalledJobAgent.py,sha256=BgDP1um-5WLSJYDbyHgLUkZocN8TrrG6QvRcffzD02E,1829
1140
1141
  DIRAC/WorkloadManagementSystem/Client/CPUNormalization.py,sha256=txBgRfnTAY5KykpKRrK1jp5x4FInWjv-Rja4R7Dqdis,5423
1141
1142
  DIRAC/WorkloadManagementSystem/Client/DownloadInputData.py,sha256=JfidM3U2b0z64hk6j0VpQ7fh6eSkRjm1Hw8X-DAspwI,16303
@@ -1179,10 +1180,10 @@ DIRAC/WorkloadManagementSystem/DB/JobDB.sql,sha256=Fo3cXMrVs6CKZgpTLGXfJrwq3VK0k
1179
1180
  DIRAC/WorkloadManagementSystem/DB/JobDBUtils.py,sha256=Tj7DrkKFrSZxkW9eqlw9_d66PgoeH83VAwWAqVVr_ZI,1595
1180
1181
  DIRAC/WorkloadManagementSystem/DB/JobLoggingDB.py,sha256=YiXQQu6WvBWwkknTch9_z43Ubzj0aRhw18SFNzni2z8,7603
1181
1182
  DIRAC/WorkloadManagementSystem/DB/JobLoggingDB.sql,sha256=hYmXOj5qGeLVSPZdipGjyVRaCcLmIxrFb7nXQ1QJrI0,1869
1182
- DIRAC/WorkloadManagementSystem/DB/JobParametersDB.py,sha256=t-q3NEO_dMTVHZ7LMI8wFWZr0ECZ_ChQskbfz-H-CU8,7791
1183
+ DIRAC/WorkloadManagementSystem/DB/JobParametersDB.py,sha256=KZd55o8VryjbWn2CdgKixAmAbj8W9lwmD_n_jlPb7z0,7771
1183
1184
  DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py,sha256=tUSuhv59CQgB7NkxsXo5r-VGXRTZ6Q4dOdhjmRi1yyg,44480
1184
1185
  DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.sql,sha256=RnCDCDGa__7sDxjSFGlu_5OwKbzxeK3a9TOMpV5ftRw,2738
1185
- DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py,sha256=a4tHv19jN2lKi4o5SYvfkG6JPbVcjJO_SgJBJORUV7Y,15631
1186
+ DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py,sha256=L_ywrVuoKlZpx07xydRY1JbMjj5-UteB1Eg8fJKF6CI,15615
1186
1187
  DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.sql,sha256=2TcyLiewFuPWqBhD43geHG0obCFRGTSLbQwPUwENYnQ,23
1187
1188
  DIRAC/WorkloadManagementSystem/DB/StatusUtils.py,sha256=cVVNiZlVbp0B-4MpkpXATlSLRtubsL6iGx4-U4KP2A4,5125
1188
1189
  DIRAC/WorkloadManagementSystem/DB/TaskQueueDB.py,sha256=4ClljoQUnHKq1KHAIFpUwL_5-NrUUuM8oHKzOZULXZg,54623
@@ -1294,9 +1295,9 @@ DIRAC/tests/Workflow/Integration/exe-script.py,sha256=B_slYdTocEzqfQLRhwuPiLyYUn
1294
1295
  DIRAC/tests/Workflow/Integration/helloWorld.py,sha256=tBgEHH3ZF7ZiTS57gtmm3DW-Qxgm_57HWHpM-Y8XSws,205
1295
1296
  DIRAC/tests/Workflow/Regression/helloWorld.py,sha256=69eCgFuVSYo-mK3Dj2dw1c6g86sF5FksKCf8V2aGVoM,509
1296
1297
  DIRAC/tests/Workflow/Regression/helloWorld.xml,sha256=xwydIcFTAHIX-YPfQfyxuQ7hzvIO3IhR3UAF7ORgkGg,5310
1297
- dirac-9.0.1.dist-info/licenses/LICENSE,sha256=uyr4oV6jmjUeepXZPPjkJRwa5q5MrI7jqJz5sVXNblQ,32452
1298
- dirac-9.0.1.dist-info/METADATA,sha256=jj1SEb6Qm_Yz6vA9Xqbcvvq4s90Pm0TcOUJvlSsJJfc,10014
1299
- dirac-9.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1300
- dirac-9.0.1.dist-info/entry_points.txt,sha256=hupzIL8aVmjK3nn7RLKdhcaiPmLOiD3Kulh3CSDHKmw,16492
1301
- dirac-9.0.1.dist-info/top_level.txt,sha256=RISrnN9kb_mPqmVu8_o4jF-DSX8-h6AcgfkO9cgfkHA,6
1302
- dirac-9.0.1.dist-info/RECORD,,
1298
+ dirac-9.0.4.dist-info/licenses/LICENSE,sha256=uyr4oV6jmjUeepXZPPjkJRwa5q5MrI7jqJz5sVXNblQ,32452
1299
+ dirac-9.0.4.dist-info/METADATA,sha256=ofzrBlYA8y8DfE4XMr1GauK7TQ0jpEO5FYZzswXwCSE,10016
1300
+ dirac-9.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1301
+ dirac-9.0.4.dist-info/entry_points.txt,sha256=hupzIL8aVmjK3nn7RLKdhcaiPmLOiD3Kulh3CSDHKmw,16492
1302
+ dirac-9.0.4.dist-info/top_level.txt,sha256=RISrnN9kb_mPqmVu8_o4jF-DSX8-h6AcgfkO9cgfkHA,6
1303
+ dirac-9.0.4.dist-info/RECORD,,
File without changes