DIRAC 9.0.0a64__py3-none-any.whl → 9.0.0a67__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- DIRAC/ConfigurationSystem/Client/LocalConfiguration.py +11 -8
- DIRAC/ConfigurationSystem/Client/VOMS2CSSynchronizer.py +1 -1
- DIRAC/Core/Security/IAMService.py +4 -3
- DIRAC/Core/Utilities/ClassAd/ClassAdLight.py +4 -290
- DIRAC/Core/Utilities/DErrno.py +5 -309
- DIRAC/Core/Utilities/JDL.py +1 -195
- DIRAC/Core/Utilities/List.py +1 -127
- DIRAC/Core/Utilities/ReturnValues.py +7 -252
- DIRAC/Core/Utilities/StateMachine.py +12 -178
- DIRAC/Core/Utilities/TimeUtilities.py +10 -253
- DIRAC/Core/Utilities/test/Test_JDL.py +0 -3
- DIRAC/Core/scripts/dirac_agent.py +1 -1
- DIRAC/DataManagementSystem/DB/FTS3DB.py +3 -0
- DIRAC/RequestManagementSystem/DB/test/RMSTestScenari.py +2 -0
- DIRAC/Resources/Catalog/RucioFileCatalogClient.py +1 -1
- DIRAC/Resources/Computing/test/Test_PoolComputingElement.py +2 -1
- DIRAC/TransformationSystem/Agent/TransformationCleaningAgent.py +1 -1
- DIRAC/Workflow/Modules/test/Test_Modules.py +5 -0
- DIRAC/WorkloadManagementSystem/Agent/JobCleaningAgent.py +1 -1
- DIRAC/WorkloadManagementSystem/Agent/StalledJobAgent.py +1 -1
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobAgent.py +2 -0
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PushJobAgent.py +1 -0
- DIRAC/WorkloadManagementSystem/Client/JobState/JobManifest.py +32 -261
- DIRAC/WorkloadManagementSystem/Client/JobStatus.py +8 -93
- DIRAC/WorkloadManagementSystem/DB/JobDBUtils.py +18 -147
- DIRAC/WorkloadManagementSystem/DB/StatusUtils.py +125 -0
- DIRAC/WorkloadManagementSystem/DB/tests/Test_StatusUtils.py +28 -0
- DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapper.py +4 -2
- DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapper.py +21 -5
- DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapperTemplate.py +4 -0
- DIRAC/WorkloadManagementSystem/Service/JobManagerHandler.py +1 -1
- DIRAC/WorkloadManagementSystem/Utilities/JobModel.py +28 -199
- DIRAC/WorkloadManagementSystem/Utilities/JobStatusUtility.py +1 -63
- DIRAC/WorkloadManagementSystem/Utilities/ParametricJob.py +7 -171
- DIRAC/WorkloadManagementSystem/Utilities/jobAdministration.py +0 -123
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobModel.py +1 -5
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_ParametricJob.py +45 -128
- DIRAC/__init__.py +55 -54
- {dirac-9.0.0a64.dist-info → dirac-9.0.0a67.dist-info}/METADATA +2 -1
- {dirac-9.0.0a64.dist-info → dirac-9.0.0a67.dist-info}/RECORD +44 -45
- DIRAC/Core/Utilities/test/Test_List.py +0 -150
- DIRAC/Core/Utilities/test/Test_Time.py +0 -88
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobAdministration.py +0 -28
- {dirac-9.0.0a64.dist-info → dirac-9.0.0a67.dist-info}/WHEEL +0 -0
- {dirac-9.0.0a64.dist-info → dirac-9.0.0a67.dist-info}/entry_points.txt +0 -0
- {dirac-9.0.0a64.dist-info → dirac-9.0.0a67.dist-info}/licenses/LICENSE +0 -0
- {dirac-9.0.0a64.dist-info → dirac-9.0.0a67.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
|
-
|
|
19
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -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)
|
|
@@ -16,6 +16,7 @@ from sqlalchemy import (
|
|
|
16
16
|
Enum,
|
|
17
17
|
Float,
|
|
18
18
|
ForeignKey,
|
|
19
|
+
Index,
|
|
19
20
|
Integer,
|
|
20
21
|
MetaData,
|
|
21
22
|
SmallInteger,
|
|
@@ -85,6 +86,7 @@ fts3JobTable = Table(
|
|
|
85
86
|
Column("error", String(2048)),
|
|
86
87
|
Column("status", Enum(*FTS3Job.ALL_STATES), server_default=FTS3Job.INIT_STATE, index=True),
|
|
87
88
|
Column("assignment", String(255), server_default=None),
|
|
89
|
+
Index("idx_jobs_lastupdate_assignment", "lastUpdate", "assignment"),
|
|
88
90
|
mysql_engine="InnoDB",
|
|
89
91
|
)
|
|
90
92
|
|
|
@@ -110,6 +112,7 @@ fts3OperationTable = Table(
|
|
|
110
112
|
Column("error", String(1024)),
|
|
111
113
|
Column("type", String(255)),
|
|
112
114
|
Column("assignment", String(255), server_default=None),
|
|
115
|
+
Index("idx_operations_lastupdate_assignment", "lastUpdate", "assignment"),
|
|
113
116
|
mysql_engine="InnoDB",
|
|
114
117
|
)
|
|
115
118
|
|
|
@@ -6,6 +6,7 @@ integration tests (Test_ReqDB.py)
|
|
|
6
6
|
# pylint: disable=invalid-name,wrong-import-position
|
|
7
7
|
import time
|
|
8
8
|
|
|
9
|
+
import pytest
|
|
9
10
|
|
|
10
11
|
from DIRAC.RequestManagementSystem.Client.Request import Request
|
|
11
12
|
from DIRAC.RequestManagementSystem.Client.Operation import Operation
|
|
@@ -42,6 +43,7 @@ def test_stress(reqDB):
|
|
|
42
43
|
assert delete["OK"], delete
|
|
43
44
|
|
|
44
45
|
|
|
46
|
+
@pytest.mark.slow
|
|
45
47
|
def test_stressBulk(reqDB):
|
|
46
48
|
"""stress test bulk"""
|
|
47
49
|
|
|
@@ -151,7 +151,7 @@ class RucioFileCatalogClient(FileCatalogClientBase):
|
|
|
151
151
|
self.authHost = options.get("AuthHost", None)
|
|
152
152
|
self.caCertPath = Locations.getCAsLocation()
|
|
153
153
|
try:
|
|
154
|
-
sLog.
|
|
154
|
+
sLog.debug(f"Logging in with a proxy located at: {self.proxyPath}")
|
|
155
155
|
sLog.debug("account: ", self.username)
|
|
156
156
|
sLog.debug("rucio host: ", self.rucioHost)
|
|
157
157
|
sLog.debug("auth host: ", self.authHost)
|
|
@@ -25,7 +25,7 @@ while True:
|
|
|
25
25
|
if os.path.isfile(stopFile):
|
|
26
26
|
os.remove(stopFile)
|
|
27
27
|
break
|
|
28
|
-
if (time.time() - start) >
|
|
28
|
+
if (time.time() - start) > 5:
|
|
29
29
|
break
|
|
30
30
|
print("End job", jobNumber, time.time())
|
|
31
31
|
"""
|
|
@@ -262,6 +262,7 @@ def test_executeJob_wholeNode8(createAndDelete):
|
|
|
262
262
|
assert "Not enough processors" in submissionResult["Message"]
|
|
263
263
|
|
|
264
264
|
|
|
265
|
+
@pytest.mark.slow
|
|
265
266
|
def test_executeJob_submitAndStop(createAndDelete):
|
|
266
267
|
time.sleep(0.5)
|
|
267
268
|
|
|
@@ -37,7 +37,7 @@ from DIRAC.WorkloadManagementSystem.Service.JobPolicy import (
|
|
|
37
37
|
RIGHT_DELETE,
|
|
38
38
|
RIGHT_KILL,
|
|
39
39
|
)
|
|
40
|
-
from DIRAC.WorkloadManagementSystem.
|
|
40
|
+
from DIRAC.WorkloadManagementSystem.DB.StatusUtils import kill_delete_jobs
|
|
41
41
|
|
|
42
42
|
# # agent's name
|
|
43
43
|
AGENT_NAME = "Transformation/TransformationCleaningAgent"
|
|
@@ -5,6 +5,8 @@ import os
|
|
|
5
5
|
import copy
|
|
6
6
|
import shutil
|
|
7
7
|
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
8
10
|
from unittest.mock import MagicMock as Mock
|
|
9
11
|
|
|
10
12
|
from DIRAC import gLogger
|
|
@@ -742,6 +744,7 @@ class FailoverRequestSuccess(ModulesTestCase):
|
|
|
742
744
|
class ScriptSuccess(ModulesTestCase):
|
|
743
745
|
#################################################
|
|
744
746
|
|
|
747
|
+
@pytest.mark.slow
|
|
745
748
|
def test_execute(self):
|
|
746
749
|
self.script.jobType = "merge"
|
|
747
750
|
self.script.stepInputData = ["foo", "bar"]
|
|
@@ -770,6 +773,7 @@ class ScriptSuccess(ModulesTestCase):
|
|
|
770
773
|
class ScriptUnicode(ModulesTestCase):
|
|
771
774
|
#################################################
|
|
772
775
|
|
|
776
|
+
@pytest.mark.slow
|
|
773
777
|
def test_execute(self):
|
|
774
778
|
self.script.jobType = "merge"
|
|
775
779
|
self.script.stepInputData = ["foo", "bar"]
|
|
@@ -799,6 +803,7 @@ class ScriptUnicode(ModulesTestCase):
|
|
|
799
803
|
class ScriptFailure(ModulesTestCase):
|
|
800
804
|
#################################################
|
|
801
805
|
|
|
806
|
+
@pytest.mark.slow
|
|
802
807
|
def test_execute(self):
|
|
803
808
|
self.script.jobType = "merge"
|
|
804
809
|
self.script.stepInputData = ["foo", "bar"]
|
|
@@ -39,7 +39,7 @@ from DIRAC.WorkloadManagementSystem.Client.WMSClient import WMSClient
|
|
|
39
39
|
from DIRAC.WorkloadManagementSystem.DB.JobDB import JobDB
|
|
40
40
|
from DIRAC.WorkloadManagementSystem.DB.SandboxMetadataDB import SandboxMetadataDB
|
|
41
41
|
from DIRAC.WorkloadManagementSystem.Service.JobPolicy import RIGHT_DELETE
|
|
42
|
-
from DIRAC.WorkloadManagementSystem.
|
|
42
|
+
from DIRAC.WorkloadManagementSystem.DB.StatusUtils import kill_delete_jobs
|
|
43
43
|
from DIRAC.WorkloadManagementSystem.Utilities.JobParameters import getJobParameters
|
|
44
44
|
|
|
45
45
|
|
|
@@ -23,7 +23,7 @@ from DIRAC.WorkloadManagementSystem.DB.JobDB import JobDB
|
|
|
23
23
|
from DIRAC.WorkloadManagementSystem.DB.JobLoggingDB import JobLoggingDB
|
|
24
24
|
from DIRAC.WorkloadManagementSystem.DB.PilotAgentsDB import PilotAgentsDB
|
|
25
25
|
from DIRAC.WorkloadManagementSystem.Service.JobPolicy import RIGHT_KILL
|
|
26
|
-
from DIRAC.WorkloadManagementSystem.
|
|
26
|
+
from DIRAC.WorkloadManagementSystem.DB.StatusUtils import kill_delete_jobs
|
|
27
27
|
from DIRAC.WorkloadManagementSystem.Utilities.JobParameters import getJobParameters
|
|
28
28
|
from DIRAC.WorkloadManagementSystem.Utilities.Utils import rescheduleJobs
|
|
29
29
|
|
|
@@ -260,6 +260,7 @@ def test__checkMatcherInfo(mocker, matcherInfo, matcherParams, expectedResult):
|
|
|
260
260
|
#############################################################################
|
|
261
261
|
|
|
262
262
|
|
|
263
|
+
@pytest.mark.slow
|
|
263
264
|
@pytest.mark.parametrize(
|
|
264
265
|
"mockGCReply, mockPMReply, expected",
|
|
265
266
|
[
|
|
@@ -308,6 +309,7 @@ def test__setupProxy(mocker, mockGCReply, mockPMReply, expected):
|
|
|
308
309
|
assert result["Message"] == expected["Message"]
|
|
309
310
|
|
|
310
311
|
|
|
312
|
+
@pytest.mark.slow
|
|
311
313
|
@pytest.mark.parametrize(
|
|
312
314
|
"mockGCReply, mockPMReply, expected",
|
|
313
315
|
[
|