DIRAC 9.0.0a54__py3-none-any.whl → 9.0.7__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 (166) hide show
  1. DIRAC/AccountingSystem/Client/AccountingCLI.py +0 -140
  2. DIRAC/AccountingSystem/Client/DataStoreClient.py +0 -13
  3. DIRAC/AccountingSystem/Client/Types/BaseAccountingType.py +0 -7
  4. DIRAC/AccountingSystem/ConfigTemplate.cfg +0 -5
  5. DIRAC/AccountingSystem/Service/DataStoreHandler.py +0 -72
  6. DIRAC/ConfigurationSystem/Client/Helpers/CSGlobals.py +0 -9
  7. DIRAC/ConfigurationSystem/Client/Helpers/Registry.py +34 -32
  8. DIRAC/ConfigurationSystem/Client/Helpers/Resources.py +11 -43
  9. DIRAC/ConfigurationSystem/Client/Helpers/test/Test_Helpers.py +0 -16
  10. DIRAC/ConfigurationSystem/Client/LocalConfiguration.py +14 -8
  11. DIRAC/ConfigurationSystem/Client/PathFinder.py +47 -8
  12. DIRAC/ConfigurationSystem/Client/SyncPlugins/CERNLDAPSyncPlugin.py +4 -1
  13. DIRAC/ConfigurationSystem/Client/VOMS2CSSynchronizer.py +9 -2
  14. DIRAC/ConfigurationSystem/Client/test/Test_PathFinder.py +41 -1
  15. DIRAC/ConfigurationSystem/private/RefresherBase.py +4 -2
  16. DIRAC/Core/DISET/ServiceReactor.py +11 -3
  17. DIRAC/Core/DISET/private/BaseClient.py +1 -2
  18. DIRAC/Core/DISET/private/Transports/M2SSLTransport.py +9 -7
  19. DIRAC/Core/Security/DiracX.py +12 -7
  20. DIRAC/Core/Security/IAMService.py +4 -3
  21. DIRAC/Core/Security/ProxyInfo.py +9 -5
  22. DIRAC/Core/Security/test/test_diracx_token_from_pem.py +161 -0
  23. DIRAC/Core/Tornado/Client/ClientSelector.py +4 -1
  24. DIRAC/Core/Tornado/Server/TornadoService.py +1 -1
  25. DIRAC/Core/Utilities/ClassAd/ClassAdLight.py +4 -290
  26. DIRAC/Core/Utilities/DErrno.py +5 -309
  27. DIRAC/Core/Utilities/Extensions.py +10 -1
  28. DIRAC/Core/Utilities/Graphs/GraphData.py +1 -1
  29. DIRAC/Core/Utilities/JDL.py +1 -195
  30. DIRAC/Core/Utilities/List.py +1 -124
  31. DIRAC/Core/Utilities/MySQL.py +101 -97
  32. DIRAC/Core/Utilities/Os.py +32 -1
  33. DIRAC/Core/Utilities/Platform.py +2 -107
  34. DIRAC/Core/Utilities/ReturnValues.py +7 -252
  35. DIRAC/Core/Utilities/StateMachine.py +12 -178
  36. DIRAC/Core/Utilities/TimeUtilities.py +10 -253
  37. DIRAC/Core/Utilities/test/Test_JDL.py +0 -3
  38. DIRAC/Core/Utilities/test/Test_Profiler.py +20 -20
  39. DIRAC/Core/scripts/dirac_agent.py +1 -1
  40. DIRAC/Core/scripts/dirac_apptainer_exec.py +16 -7
  41. DIRAC/Core/scripts/dirac_platform.py +1 -92
  42. DIRAC/DataManagementSystem/Agent/FTS3Agent.py +8 -7
  43. DIRAC/DataManagementSystem/Agent/RequestOperations/RemoveFile.py +7 -6
  44. DIRAC/DataManagementSystem/Client/FTS3Job.py +71 -34
  45. DIRAC/DataManagementSystem/DB/FTS3DB.py +3 -0
  46. DIRAC/DataManagementSystem/DB/FileCatalogComponents/DatasetManager/DatasetManager.py +1 -1
  47. DIRAC/DataManagementSystem/Utilities/DMSHelpers.py +6 -2
  48. DIRAC/DataManagementSystem/scripts/dirac_dms_create_moving_request.py +2 -0
  49. DIRAC/DataManagementSystem/scripts/dirac_dms_protocol_matrix.py +0 -1
  50. DIRAC/FrameworkSystem/Client/ComponentInstaller.py +4 -2
  51. DIRAC/FrameworkSystem/DB/ProxyDB.py +9 -5
  52. DIRAC/FrameworkSystem/Utilities/TokenManagementUtilities.py +3 -2
  53. DIRAC/FrameworkSystem/Utilities/diracx.py +2 -74
  54. DIRAC/FrameworkSystem/private/authorization/AuthServer.py +2 -2
  55. DIRAC/FrameworkSystem/scripts/dirac_login.py +2 -2
  56. DIRAC/FrameworkSystem/scripts/dirac_proxy_init.py +1 -1
  57. DIRAC/Interfaces/API/Dirac.py +27 -13
  58. DIRAC/Interfaces/API/DiracAdmin.py +42 -7
  59. DIRAC/Interfaces/API/Job.py +1 -0
  60. DIRAC/Interfaces/scripts/dirac_admin_allow_site.py +7 -1
  61. DIRAC/Interfaces/scripts/dirac_admin_ban_site.py +7 -1
  62. DIRAC/Interfaces/scripts/dirac_wms_job_parameters.py +0 -1
  63. DIRAC/MonitoringSystem/Client/Types/WMSHistory.py +4 -0
  64. DIRAC/MonitoringSystem/Client/WebAppClient.py +26 -0
  65. DIRAC/MonitoringSystem/ConfigTemplate.cfg +9 -0
  66. DIRAC/MonitoringSystem/DB/MonitoringDB.py +6 -25
  67. DIRAC/MonitoringSystem/Service/MonitoringHandler.py +0 -33
  68. DIRAC/MonitoringSystem/Service/WebAppHandler.py +599 -0
  69. DIRAC/MonitoringSystem/private/MainReporter.py +0 -3
  70. DIRAC/ProductionSystem/scripts/dirac_prod_get_trans.py +2 -3
  71. DIRAC/RequestManagementSystem/Agent/RequestExecutingAgent.py +8 -6
  72. DIRAC/RequestManagementSystem/ConfigTemplate.cfg +6 -6
  73. DIRAC/RequestManagementSystem/DB/test/RMSTestScenari.py +2 -0
  74. DIRAC/ResourceStatusSystem/Client/SiteStatus.py +4 -2
  75. DIRAC/ResourceStatusSystem/Command/FreeDiskSpaceCommand.py +3 -1
  76. DIRAC/ResourceStatusSystem/Utilities/CSHelpers.py +2 -31
  77. DIRAC/ResourceStatusSystem/scripts/dirac_rss_set_status.py +18 -4
  78. DIRAC/Resources/Catalog/RucioFileCatalogClient.py +1 -1
  79. DIRAC/Resources/Computing/AREXComputingElement.py +19 -3
  80. DIRAC/Resources/Computing/BatchSystems/Condor.py +126 -108
  81. DIRAC/Resources/Computing/BatchSystems/SLURM.py +5 -1
  82. DIRAC/Resources/Computing/BatchSystems/test/Test_SLURM.py +46 -0
  83. DIRAC/Resources/Computing/HTCondorCEComputingElement.py +37 -43
  84. DIRAC/Resources/Computing/SingularityComputingElement.py +6 -1
  85. DIRAC/Resources/Computing/test/Test_HTCondorCEComputingElement.py +67 -49
  86. DIRAC/Resources/Computing/test/Test_PoolComputingElement.py +2 -1
  87. DIRAC/Resources/IdProvider/CheckInIdProvider.py +13 -0
  88. DIRAC/Resources/IdProvider/IdProviderFactory.py +11 -3
  89. DIRAC/Resources/Storage/StorageBase.py +4 -2
  90. DIRAC/Resources/Storage/StorageElement.py +4 -4
  91. DIRAC/TransformationSystem/Agent/TaskManagerAgentBase.py +10 -16
  92. DIRAC/TransformationSystem/Agent/TransformationAgent.py +22 -1
  93. DIRAC/TransformationSystem/Agent/TransformationCleaningAgent.py +15 -15
  94. DIRAC/TransformationSystem/Client/Transformation.py +2 -1
  95. DIRAC/TransformationSystem/Client/TransformationClient.py +0 -7
  96. DIRAC/TransformationSystem/Client/Utilities.py +9 -0
  97. DIRAC/TransformationSystem/Service/TransformationManagerHandler.py +0 -336
  98. DIRAC/TransformationSystem/Utilities/ReplicationCLIParameters.py +3 -3
  99. DIRAC/TransformationSystem/scripts/dirac_production_runjoblocal.py +2 -4
  100. DIRAC/TransformationSystem/test/Test_replicationTransformation.py +5 -6
  101. DIRAC/Workflow/Modules/test/Test_Modules.py +5 -0
  102. DIRAC/WorkloadManagementSystem/Agent/JobAgent.py +1 -5
  103. DIRAC/WorkloadManagementSystem/Agent/JobCleaningAgent.py +11 -7
  104. DIRAC/WorkloadManagementSystem/Agent/PilotSyncAgent.py +4 -3
  105. DIRAC/WorkloadManagementSystem/Agent/PushJobAgent.py +13 -13
  106. DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py +10 -13
  107. DIRAC/WorkloadManagementSystem/Agent/StalledJobAgent.py +18 -51
  108. DIRAC/WorkloadManagementSystem/Agent/StatesAccountingAgent.py +41 -1
  109. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobAgent.py +2 -0
  110. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobCleaningAgent.py +7 -9
  111. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PushJobAgent.py +1 -0
  112. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_SiteDirector.py +8 -2
  113. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_StalledJobAgent.py +4 -5
  114. DIRAC/WorkloadManagementSystem/Client/DownloadInputData.py +7 -5
  115. DIRAC/WorkloadManagementSystem/Client/JobMonitoringClient.py +10 -11
  116. DIRAC/WorkloadManagementSystem/Client/JobState/JobManifest.py +32 -261
  117. DIRAC/WorkloadManagementSystem/Client/JobStateUpdateClient.py +3 -0
  118. DIRAC/WorkloadManagementSystem/Client/JobStatus.py +8 -152
  119. DIRAC/WorkloadManagementSystem/Client/SandboxStoreClient.py +25 -38
  120. DIRAC/WorkloadManagementSystem/Client/WMSClient.py +2 -3
  121. DIRAC/WorkloadManagementSystem/Client/test/Test_Client_DownloadInputData.py +29 -0
  122. DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg +4 -8
  123. DIRAC/WorkloadManagementSystem/DB/JobDB.py +40 -69
  124. DIRAC/WorkloadManagementSystem/DB/JobDBUtils.py +18 -147
  125. DIRAC/WorkloadManagementSystem/DB/JobParametersDB.py +9 -9
  126. DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py +3 -2
  127. DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py +28 -39
  128. DIRAC/WorkloadManagementSystem/DB/StatusUtils.py +125 -0
  129. DIRAC/WorkloadManagementSystem/DB/tests/Test_JobDB.py +1 -1
  130. DIRAC/WorkloadManagementSystem/DB/tests/Test_StatusUtils.py +28 -0
  131. DIRAC/WorkloadManagementSystem/Executor/JobSanity.py +3 -3
  132. DIRAC/WorkloadManagementSystem/FutureClient/JobStateUpdateClient.py +2 -14
  133. DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapper.py +14 -9
  134. DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapper.py +36 -10
  135. DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapperTemplate.py +4 -0
  136. DIRAC/WorkloadManagementSystem/Service/JobManagerHandler.py +33 -154
  137. DIRAC/WorkloadManagementSystem/Service/JobMonitoringHandler.py +5 -323
  138. DIRAC/WorkloadManagementSystem/Service/JobStateUpdateHandler.py +0 -16
  139. DIRAC/WorkloadManagementSystem/Service/PilotManagerHandler.py +6 -102
  140. DIRAC/WorkloadManagementSystem/Service/SandboxStoreHandler.py +5 -51
  141. DIRAC/WorkloadManagementSystem/Service/WMSAdministratorHandler.py +16 -79
  142. DIRAC/WorkloadManagementSystem/Utilities/JobModel.py +28 -199
  143. DIRAC/WorkloadManagementSystem/Utilities/JobParameters.py +65 -3
  144. DIRAC/WorkloadManagementSystem/Utilities/JobStatusUtility.py +2 -64
  145. DIRAC/WorkloadManagementSystem/Utilities/ParametricJob.py +7 -171
  146. DIRAC/WorkloadManagementSystem/Utilities/PilotCStoJSONSynchronizer.py +73 -7
  147. DIRAC/WorkloadManagementSystem/Utilities/PilotWrapper.py +2 -0
  148. DIRAC/WorkloadManagementSystem/Utilities/RemoteRunner.py +16 -0
  149. DIRAC/WorkloadManagementSystem/Utilities/Utils.py +36 -1
  150. DIRAC/WorkloadManagementSystem/Utilities/jobAdministration.py +15 -0
  151. DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobModel.py +1 -5
  152. DIRAC/WorkloadManagementSystem/Utilities/test/Test_ParametricJob.py +45 -128
  153. DIRAC/WorkloadManagementSystem/Utilities/test/Test_PilotWrapper.py +16 -0
  154. DIRAC/__init__.py +55 -54
  155. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/METADATA +6 -4
  156. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/RECORD +160 -160
  157. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/WHEEL +1 -1
  158. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/entry_points.txt +0 -3
  159. DIRAC/Core/Utilities/test/Test_List.py +0 -150
  160. DIRAC/Core/Utilities/test/Test_Time.py +0 -88
  161. DIRAC/TransformationSystem/scripts/dirac_transformation_archive.py +0 -30
  162. DIRAC/TransformationSystem/scripts/dirac_transformation_clean.py +0 -30
  163. DIRAC/TransformationSystem/scripts/dirac_transformation_remove_output.py +0 -30
  164. DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobManager.py +0 -58
  165. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/licenses/LICENSE +0 -0
  166. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/top_level.txt +0 -0
@@ -1,260 +1,17 @@
1
- """
2
- DIRAC TimeUtilities module
3
- Support for basic Date and Time operations
4
- based on system datetime module.
5
-
6
- It provides common interface to UTC timestamps,
7
- converter to string types and back.
8
-
9
- Useful timedelta constant are also provided to
10
- define time intervals.
11
-
12
- Notice: datetime.timedelta objects allow multiplication and division by interger
13
- but not by float. Thus:
14
-
15
- - DIRAC.TimeUtilities.second * 1.5 is not allowed
16
- - DIRAC.TimeUtilities.second * 3 / 2 is allowed
1
+ """Backward compatibility wrapper - moved to DIRACCommon
17
2
 
18
- An timeInterval class provides a method to check
19
- if a give datetime is in the defined interval.
3
+ This module has been moved to DIRACCommon.Core.Utilities.TimeUtilities to avoid
4
+ circular dependencies and allow DiracX to use these utilities without
5
+ triggering DIRAC's global state initialization.
20
6
 
7
+ All exports are maintained for backward compatibility.
21
8
  """
22
- import datetime
23
- import sys
24
- import time
25
-
26
- from DIRAC import gLogger
27
-
28
- # Some useful constants for time operations
29
- microsecond = datetime.timedelta(microseconds=1)
30
- second = datetime.timedelta(seconds=1)
31
- minute = datetime.timedelta(minutes=1)
32
- hour = datetime.timedelta(hours=1)
33
- day = datetime.timedelta(days=1)
34
- week = datetime.timedelta(days=7)
35
-
36
-
37
- def timeThis(method):
38
- """Function to be used as a decorator for timing other functions/methods"""
39
-
40
- def timed(*args, **kw):
41
- """What actually times"""
42
- ts = time.time()
43
- result = method(*args, **kw)
44
- if sys.stdout.isatty():
45
- return result
46
- te = time.time()
47
-
48
- pre = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC ")
49
-
50
- try:
51
- pre += args[0].log.getName() + "/" + args[0].log.getSubName() + " TIME: " + args[0].transString
52
- except AttributeError:
53
- try:
54
- pre += args[0].log.getName() + " TIME: " + args[0].transString
55
- except AttributeError:
56
- try:
57
- pre += args[0].log.getName() + "/" + args[0].log.getSubName() + " TIME: "
58
- except AttributeError:
59
- pre += "TIME: "
60
- except IndexError:
61
- pre += "TIME: "
62
-
63
- argsLen = ""
64
- if args:
65
- try:
66
- if isinstance(args[1], (list, dict)):
67
- argsLen = f"arguments len: {len(args[1])}"
68
- except IndexError:
69
- if kw:
70
- try:
71
- if isinstance(list(list(kw.items())[0])[1], (list, dict)):
72
- argsLen = f"arguments len: {len(list(list(kw.items())[0])[1])}"
73
- except IndexError:
74
- argsLen = ""
75
-
76
- gLogger.info(f"{pre} Exec time ===> function {method.__name__!r} {argsLen} -> {te - ts:2.2f} sec")
77
- return result
78
-
79
- return timed
80
-
81
-
82
- def toEpoch(dateTimeObject=None):
83
- """
84
- Get seconds since epoch. Accepts datetime or date objects
85
- """
86
- return toEpochMilliSeconds(dateTimeObject) // 1000
9
+ from functools import partial
87
10
 
11
+ # Re-export everything from DIRACCommon for backward compatibility
12
+ from DIRACCommon.Core.Utilities.TimeUtilities import * # noqa: F401, F403
88
13
 
89
- def toEpochMilliSeconds(dateTimeObject=None):
90
- """
91
- Get milliseconds since epoch
92
- """
93
- if dateTimeObject is None:
94
- dateTimeObject = datetime.datetime.utcnow()
95
- if dateTimeObject.resolution == datetime.timedelta(days=1):
96
- # Add time information corresponding to midnight UTC if it's a datetime.date
97
- dateTimeObject = datetime.datetime.combine(
98
- dateTimeObject, datetime.time.min.replace(tzinfo=datetime.timezone.utc)
99
- )
100
- posixTime = dateTimeObject.replace(tzinfo=datetime.timezone.utc).timestamp()
101
- return int(posixTime * 1000)
102
-
103
-
104
- def fromEpoch(epoch):
105
- """
106
- Get datetime object from epoch
107
- """
108
- # Check if the timestamp is in milliseconds
109
- if epoch > 10**17: # nanoseconds
110
- epoch /= 1000**3
111
- elif epoch > 10**14: # microseconds
112
- epoch /= 1000**2
113
- elif epoch > 10**11: # milliseconds
114
- epoch /= 1000
115
- return datetime.datetime.utcfromtimestamp(epoch)
116
-
117
-
118
- def toString(myDate=None):
119
- """
120
- Convert to String
121
- if argument type is neither _dateTimeType, _dateType, nor _timeType
122
- the current dateTime converted to String is returned instead
123
-
124
- Notice: datetime.timedelta are converted to strings using the format:
125
- [day] days [hour]:[min]:[sec]:[microsec]
126
- where hour, min, sec, microsec are always positive integers,
127
- and day carries the sign.
128
- To keep internal consistency we are using:
129
- [hour]:[min]:[sec]:[microsec]
130
- where min, sec, microsec are always positive integers and hour carries the sign.
131
- """
132
- if isinstance(myDate, datetime.date):
133
- return str(myDate)
134
-
135
- elif isinstance(myDate, datetime.time):
136
- return "%02d:%02d:%02d.%06d" % (
137
- myDate.days * 24 + myDate.seconds / 3600,
138
- myDate.seconds % 3600 / 60,
139
- myDate.seconds % 60,
140
- myDate.microseconds,
141
- )
142
- else:
143
- return toString(datetime.datetime.utcnow())
144
-
145
-
146
- def fromString(myDate=None):
147
- """
148
- Convert date/time/datetime String back to appropriated objects
149
-
150
- The format of the string it is assume to be that returned by toString method.
151
- See notice on toString method
152
- On Error, return None
153
-
154
- :param myDate: the date string to be converted
155
- :type myDate: str or datetime.datetime
156
- """
157
- if isinstance(myDate, datetime.datetime):
158
- return myDate
159
- if isinstance(myDate, str):
160
- if myDate.find(" ") > 0:
161
- dateTimeTuple = myDate.split(" ")
162
- dateTuple = dateTimeTuple[0].split("-")
163
- try:
164
- return datetime.datetime(year=dateTuple[0], month=dateTuple[1], day=dateTuple[2]) + fromString(
165
- dateTimeTuple[1]
166
- )
167
- # return datetime.datetime.utcnow().combine( fromString( dateTimeTuple[0] ),
168
- # fromString( dateTimeTuple[1] ) )
169
- except Exception:
170
- try:
171
- return datetime.datetime(
172
- year=int(dateTuple[0]), month=int(dateTuple[1]), day=int(dateTuple[2])
173
- ) + fromString(dateTimeTuple[1])
174
- except ValueError:
175
- return None
176
- # return datetime.datetime.utcnow().combine( fromString( dateTimeTuple[0] ),
177
- # fromString( dateTimeTuple[1] ) )
178
- elif myDate.find(":") > 0:
179
- timeTuple = myDate.replace(".", ":").split(":")
180
- try:
181
- if len(timeTuple) == 4:
182
- return datetime.timedelta(
183
- hours=int(timeTuple[0]),
184
- minutes=int(timeTuple[1]),
185
- seconds=int(timeTuple[2]),
186
- microseconds=int(timeTuple[3]),
187
- )
188
- elif len(timeTuple) == 3:
189
- try:
190
- return datetime.timedelta(
191
- hours=int(timeTuple[0]),
192
- minutes=int(timeTuple[1]),
193
- seconds=int(timeTuple[2]),
194
- microseconds=0,
195
- )
196
- except ValueError:
197
- return None
198
- else:
199
- return None
200
- except Exception:
201
- return None
202
- elif myDate.find("-") > 0:
203
- dateTuple = myDate.split("-")
204
- try:
205
- return datetime.date(int(dateTuple[0]), int(dateTuple[1]), int(dateTuple[2]))
206
- except Exception:
207
- return None
208
-
209
- return None
210
-
211
-
212
- class timeInterval:
213
- """
214
- Simple class to define a timeInterval object able to check if a given
215
- dateTime is inside
216
- """
217
-
218
- def __init__(self, initialDateTime, intervalTimeDelta):
219
- """
220
- Initialization method, it requires the initial dateTime and the
221
- timedelta that define the limits.
222
- The upper limit is not included thus it is [begin,end)
223
- If not properly initialized an error flag is set, and subsequent calls
224
- to any method will return None
225
- """
226
- if not isinstance(initialDateTime, datetime.datetime) or not isinstance(intervalTimeDelta, datetime.timedelta):
227
- self.__error = True
228
- return None
229
- self.__error = False
230
- if intervalTimeDelta.days < 0:
231
- self.__startDateTime = initialDateTime + intervalTimeDelta
232
- self.__endDateTime = initialDateTime
233
- else:
234
- self.__startDateTime = initialDateTime
235
- self.__endDateTime = initialDateTime + intervalTimeDelta
236
-
237
- def includes(self, myDateTime):
238
- """ """
239
- if self.__error:
240
- return None
241
- if not isinstance(myDateTime, datetime.datetime):
242
- return None
243
- if myDateTime < self.__startDateTime:
244
- return False
245
- if myDateTime >= self.__endDateTime:
246
- return False
247
- return True
248
-
249
-
250
- def queryTime(f):
251
- """Decorator to measure the function call time"""
14
+ from DIRAC import gLogger
252
15
 
253
- def measureQueryTime(*args, **kwargs):
254
- start = time.time()
255
- result = f(*args, **kwargs)
256
- if result["OK"] and "QueryTime" not in result:
257
- result["QueryTime"] = time.time() - start
258
- return result
259
16
 
260
- return measureQueryTime
17
+ timeThis = partial(timeThis, logger_info=gLogger.info)
@@ -19,9 +19,6 @@ def jdl_monkey_business(monkeypatch):
19
19
  monkeypatch.setattr("DIRAC.Core.Base.API.getSites", lambda: S_OK(["LCG.IN2P3.fr"]))
20
20
  monkeypatch.setattr("DIRAC.WorkloadManagementSystem.Utilities.JobModel.getSites", lambda: S_OK(["LCG.IN2P3.fr"]))
21
21
  monkeypatch.setattr("DIRAC.Interfaces.API.Job.getDIRACPlatforms", lambda: S_OK("x86_64-slc6-gcc49-opt"))
22
- monkeypatch.setattr(
23
- "DIRAC.WorkloadManagementSystem.Utilities.JobModel.getDIRACPlatforms", lambda: S_OK("x86_64-slc6-gcc49-opt")
24
- )
25
22
  yield
26
23
 
27
24
 
@@ -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
@@ -25,7 +25,7 @@ def main():
25
25
  localCfg.setConfigurationForAgent(agentName)
26
26
  localCfg.addDefaultEntry("/DIRAC/Security/UseServerCertificate", "yes")
27
27
  localCfg.addDefaultEntry("LogColor", True)
28
- resultDict = localCfg.loadUserData()
28
+ resultDict = localCfg.loadUserData(requireSuccessfulSync=True)
29
29
  if not resultDict["OK"]:
30
30
  gLogger.error("There were errors when loading configuration", resultDict["Message"])
31
31
  sys.exit(1)
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env python
2
- """ Starts a DIRAC command inside an apptainer container.
3
- """
2
+ """Starts a DIRAC command inside an apptainer container."""
4
3
 
5
4
  import os
6
5
  import sys
@@ -10,6 +9,7 @@ import DIRAC
10
9
  from DIRAC import S_ERROR, gConfig, gLogger
11
10
  from DIRAC.Core.Base.Script import Script
12
11
  from DIRAC.Core.Security.Locations import getCAsLocation, getProxyLocation, getVOMSLocation
12
+ from DIRAC.Core.Utilities.Os import safe_listdir
13
13
  from DIRAC.Core.Utilities.Subprocess import systemCall
14
14
 
15
15
 
@@ -51,8 +51,9 @@ def main():
51
51
  if switch[0].lower() == "i" or switch[0].lower() == "image":
52
52
  user_image = switch[1]
53
53
 
54
- dirac_env_var = os.environ.get("DIRAC", os.getcwd())
55
- diracos_env_var = os.environ.get("DIRACOS", os.getcwd())
54
+ cwd = os.path.realpath(os.getcwd())
55
+ dirac_env_var = os.environ.get("DIRAC", cwd)
56
+ diracos_env_var = os.environ.get("DIRACOS", cwd)
56
57
  etc_dir = os.path.join(DIRAC.rootPath, "etc")
57
58
  rc_script = os.path.join(os.path.realpath(sys.base_prefix), "diracosrc")
58
59
 
@@ -73,7 +74,7 @@ def main():
73
74
  cmd.extend(["--contain"]) # use minimal /dev and empty other directories (e.g. /tmp and $HOME)
74
75
  cmd.extend(["--ipc"]) # run container in a new IPC namespace
75
76
  cmd.extend(["--pid"]) # run container in a new PID namespace
76
- cmd.extend(["--bind", f"{os.getcwd()}:/mnt"]) # bind current directory for dirac_container.sh
77
+ cmd.extend(["--bind", cwd]) # bind current directory for dirac_container.sh
77
78
  if proxy_location:
78
79
  cmd.extend(["--bind", f"{proxy_location}:/etc/proxy"]) # bind proxy file
79
80
  cmd.extend(["--bind", f"{getCAsLocation()}:/etc/grid-security/certificates"]) # X509_CERT_DIR
@@ -83,11 +84,18 @@ def main():
83
84
  cmd.extend(["--bind", f"{vomses_location}:/etc/grid-security/vomses"]) # X509_VOMSES
84
85
  cmd.extend(["--bind", "{0}:{0}:ro".format(etc_dir)]) # etc dir for dirac.cfg
85
86
  cmd.extend(["--bind", "{0}:{0}:ro".format(os.path.join(os.path.realpath(sys.base_prefix)))]) # code dir
87
+ # here bind optional paths
88
+ for bind_path in gConfig.getValue("/Resources/Computing/Singularity/BindPaths", []):
89
+ if safe_listdir(bind_path):
90
+ cmd.extend(["--bind", f"{bind_path}:{bind_path}"])
91
+ else:
92
+ gLogger.warn(f"Bind path {bind_path} does not exist, skipping")
93
+ cmd.extend(["--cwd", cwd]) # set working directory
86
94
 
87
95
  rootImage = user_image or gConfig.getValue("/Resources/Computing/Singularity/ContainerRoot") or CONTAINER_DEFROOT
88
96
 
89
97
  if os.path.isdir(rootImage) or os.path.isfile(rootImage):
90
- cmd.extend([rootImage, "/mnt/dirac_container.sh"])
98
+ cmd.extend([rootImage, f"{cwd}/dirac_container.sh"])
91
99
  else:
92
100
  # if we are here is because there's no image, or it is not accessible (e.g. not on CVMFS)
93
101
  gLogger.error("Apptainer image to exec not found: ", rootImage)
@@ -99,7 +107,8 @@ def main():
99
107
  gLogger.error(result["Message"])
100
108
  DIRAC.exit(1)
101
109
  if result["Value"][0] != 0:
102
- gLogger.error(result["Value"][2])
110
+ gLogger.error("Apptainer command failed with exit code", result["Value"][0])
111
+ gLogger.error("Command output:", result["Value"])
103
112
  DIRAC.exit(2)
104
113
  gLogger.notice(result["Value"][1])
105
114
 
@@ -23,107 +23,16 @@ try:
23
23
  except Exception:
24
24
  import argparse
25
25
  import platform
26
- import os
27
- import sys
28
- import re
29
- import subprocess
30
26
 
31
27
  parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
32
28
  parser.parse_known_args()
33
29
 
34
- # We need to patch python platform module. It does a string comparison for the libc versions.
35
- # it fails when going from 2.9 to 2.10,
36
- # the fix converts the version to a tuple and attempts a numeric comparison
37
-
38
- _libc_search = re.compile(r"(__libc_init)" "|" "(GLIBC_([0-9.]+))" "|" r"(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)")
39
-
40
- def libc_ver(executable=sys.executable, lib="", version="", chunksize=2048):
41
- """Tries to determine the libc version that the file executable
42
- (which defaults to the Python interpreter) is linked against.
43
-
44
- Returns a tuple of strings (lib,version) which default to the
45
- given parameters in case the lookup fails.
46
-
47
- Note that the function has intimate knowledge of how different
48
- libc versions add symbols to the executable and thus is probably
49
- only useable for executables compiled using gcc.
50
-
51
- The file is read and scanned in chunks of chunksize bytes.
52
-
53
- """
54
- with open(executable, "rb") as f:
55
- binary = f.read(chunksize)
56
- pos = 0
57
- version = [0, 0, 0]
58
- while True:
59
- m = _libc_search.search(binary, pos)
60
- if not m:
61
- binary = f.read(chunksize)
62
- if not binary:
63
- break
64
- pos = 0
65
- continue
66
- libcinit, glibc, glibcversion, so, threads, soversion = m.groups()
67
- if libcinit and not lib:
68
- lib = "libc"
69
- elif glibc:
70
- glibcversion_parts = glibcversion.split(".")
71
- for i, part in enumerate(glibcversion_parts):
72
- try:
73
- glibcversion_parts[i] = int(part)
74
- except ValueError:
75
- glibcversion_parts[i] = 0
76
- if libcinit and not lib:
77
- lib = "libc"
78
- elif glibc:
79
- if lib != "glibc":
80
- lib = "glibc"
81
- version = glibcversion_parts
82
- elif glibcversion_parts > version:
83
- version = glibcversion_parts
84
- elif so:
85
- if lib != "glibc":
86
- lib = "libc"
87
- version = max(version, soversion)
88
- if threads and version[-len(threads) :] != threads:
89
- version = version + threads
90
- pos = m.end()
91
- return lib, ".".join(map(str, version))
92
-
93
30
  # Command line interface
94
31
  def getPlatformString():
95
32
  # Modified to return our desired platform string, R. Graciani
96
33
  platformTuple = (platform.system(), platform.machine())
97
34
  if platformTuple[0] == "Linux":
98
- sp = subprocess.Popen(["/sbin/ldconfig", "--print-cache"], stdout=subprocess.PIPE)
99
- ldre = re.compile(r".*=> (.*/libc\.so\..*$)")
100
- libs = []
101
- for line in sp.stdout.readlines():
102
- reM = ldre.match(line)
103
- if reM:
104
- libs.append(reM.groups()[0])
105
- if not libs:
106
- # get version of higher libc installed
107
- if platform.machine().find("64") != -1:
108
- lib = "/lib64"
109
- else:
110
- lib = "/lib"
111
- for libFile in os.listdir(lib):
112
- if libFile.find("libc-") == 0 or libFile.find("libc.so") == 0:
113
- libs.append(os.path.join(lib, libFile))
114
- newest_lib = [0, 0, 0]
115
- for lib in libs:
116
- lib_parts = libc_ver(lib)[1].split(".")
117
- for i, part in enumerate(lib_parts):
118
- try:
119
- lib_parts[i] = int(part)
120
- except ValueError:
121
- lib_parts[i] = 0
122
- # print "non integer version numbers"
123
- if lib_parts > newest_lib:
124
- newest_lib = lib_parts
125
-
126
- platformTuple += ("glibc-" + ".".join(map(str, newest_lib)),)
35
+ platformTuple += ("-".join(platform.libc_ver()),)
127
36
  elif platformTuple[0] == "Darwin":
128
37
  platformTuple += (".".join(platform.mac_ver()[0].split(".")[:2]),)
129
38
  else:
@@ -719,10 +719,11 @@ class FTS3Agent(AgentModule):
719
719
  return self.dataOpSender.concludeSending()
720
720
 
721
721
  def __sendAccounting(self, ftsJob):
722
- self.dataOpSender.sendData(
723
- ftsJob.accountingDict,
724
- commitFlag=True,
725
- delayedCommit=True,
726
- startTime=fromString(ftsJob.submitTime),
727
- endTime=fromString(ftsJob.lastUpdate),
728
- )
722
+ for accountingDict in ftsJob.accountingDicts:
723
+ self.dataOpSender.sendData(
724
+ accountingDict,
725
+ commitFlag=True,
726
+ delayedCommit=True,
727
+ startTime=fromString(ftsJob.submitTime),
728
+ endTime=fromString(ftsJob.lastUpdate),
729
+ )
@@ -4,17 +4,17 @@
4
4
  # Date: 2013/03/25 07:44:19
5
5
  ########################################################################
6
6
 
7
- """ :mod: RemoveFile
7
+ """:mod: RemoveFile
8
8
 
9
- ================
9
+ ================
10
10
 
11
- .. module: RemoveFile
11
+ .. module: RemoveFile
12
12
 
13
- :synopsis: removeFile operation handler
13
+ :synopsis: removeFile operation handler
14
14
 
15
- .. moduleauthor:: Krzysztof.Ciba@NOSPAMgmail.com
15
+ .. moduleauthor:: Krzysztof.Ciba@NOSPAMgmail.com
16
16
 
17
- removeFile operation handler
17
+ removeFile operation handler
18
18
  """
19
19
  # #
20
20
  # @file RemoveFile.py
@@ -132,6 +132,7 @@ class RemoveFile(DMSRequestOperationsBase):
132
132
  self.rmsMonitoringReporter.addRecord(
133
133
  self.createRMSRecord("Successful", len(toRemoveDict) - len(bulkRemoval["Value"]))
134
134
  )
135
+ toRemoveDict = bulkRemoval["Value"]
135
136
 
136
137
  # # 2nd step - single file removal
137
138
  for lfn, opFile in toRemoveDict.items():