DIRAC 9.0.0a60__py3-none-any.whl → 9.0.0a62__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/AccountingSystem/Client/AccountingCLI.py +0 -140
- DIRAC/AccountingSystem/Client/DataStoreClient.py +0 -13
- DIRAC/AccountingSystem/Client/Types/BaseAccountingType.py +0 -7
- DIRAC/AccountingSystem/ConfigTemplate.cfg +0 -5
- DIRAC/AccountingSystem/Service/DataStoreHandler.py +0 -72
- DIRAC/ConfigurationSystem/Client/Helpers/Registry.py +34 -6
- DIRAC/ConfigurationSystem/Client/LocalConfiguration.py +3 -0
- DIRAC/ConfigurationSystem/Client/VOMS2CSSynchronizer.py +8 -1
- DIRAC/Core/DISET/private/BaseClient.py +1 -2
- DIRAC/Core/Security/ProxyInfo.py +9 -5
- DIRAC/Core/Utilities/Os.py +32 -1
- DIRAC/Core/scripts/dirac_apptainer_exec.py +12 -4
- DIRAC/DataManagementSystem/Utilities/DMSHelpers.py +5 -1
- DIRAC/Interfaces/API/DiracAdmin.py +17 -5
- DIRAC/Interfaces/scripts/dirac_admin_allow_site.py +7 -1
- DIRAC/Interfaces/scripts/dirac_admin_ban_site.py +7 -1
- DIRAC/MonitoringSystem/Client/Types/WMSHistory.py +4 -0
- DIRAC/MonitoringSystem/DB/MonitoringDB.py +0 -20
- DIRAC/MonitoringSystem/Service/MonitoringHandler.py +0 -33
- DIRAC/MonitoringSystem/Service/WebAppHandler.py +68 -1
- DIRAC/ResourceStatusSystem/Client/SiteStatus.py +4 -2
- DIRAC/ResourceStatusSystem/Utilities/CSHelpers.py +2 -31
- DIRAC/ResourceStatusSystem/scripts/dirac_rss_set_status.py +18 -4
- DIRAC/Resources/Computing/BatchSystems/Condor.py +126 -108
- DIRAC/Resources/Computing/HTCondorCEComputingElement.py +33 -15
- DIRAC/Resources/Computing/test/Test_HTCondorCEComputingElement.py +67 -49
- DIRAC/Resources/Storage/StorageBase.py +4 -2
- DIRAC/TransformationSystem/Agent/TaskManagerAgentBase.py +10 -13
- DIRAC/TransformationSystem/Agent/TransformationAgent.py +22 -1
- DIRAC/TransformationSystem/Agent/TransformationCleaningAgent.py +6 -3
- DIRAC/TransformationSystem/Client/Utilities.py +6 -0
- DIRAC/WorkloadManagementSystem/Agent/JobCleaningAgent.py +4 -3
- DIRAC/WorkloadManagementSystem/Agent/StatesAccountingAgent.py +34 -1
- DIRAC/WorkloadManagementSystem/Client/JobMonitoringClient.py +0 -9
- DIRAC/WorkloadManagementSystem/Client/SandboxStoreClient.py +0 -37
- DIRAC/WorkloadManagementSystem/DB/JobDB.py +0 -58
- DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py +25 -37
- DIRAC/WorkloadManagementSystem/Executor/JobSanity.py +3 -3
- DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapper.py +9 -6
- DIRAC/WorkloadManagementSystem/Service/JobManagerHandler.py +0 -10
- DIRAC/WorkloadManagementSystem/Service/JobMonitoringHandler.py +0 -126
- DIRAC/WorkloadManagementSystem/Service/PilotManagerHandler.py +6 -3
- DIRAC/WorkloadManagementSystem/Service/SandboxStoreHandler.py +5 -51
- {dirac-9.0.0a60.dist-info → dirac-9.0.0a62.dist-info}/METADATA +1 -1
- {dirac-9.0.0a60.dist-info → dirac-9.0.0a62.dist-info}/RECORD +49 -49
- {dirac-9.0.0a60.dist-info → dirac-9.0.0a62.dist-info}/WHEEL +0 -0
- {dirac-9.0.0a60.dist-info → dirac-9.0.0a62.dist-info}/entry_points.txt +0 -0
- {dirac-9.0.0a60.dist-info → dirac-9.0.0a62.dist-info}/licenses/LICENSE +0 -0
- {dirac-9.0.0a60.dist-info → dirac-9.0.0a62.dist-info}/top_level.txt +0 -0
|
@@ -13,6 +13,9 @@ from DIRAC.Core.Base.Script import Script
|
|
|
13
13
|
@Script()
|
|
14
14
|
def main():
|
|
15
15
|
Script.registerSwitch("E:", "email=", "Boolean True/False (True by default)")
|
|
16
|
+
Script.registerSwitch(
|
|
17
|
+
"", "days=", "Number of days the token is valid for. Default is 1 day. 0 or less days denotes forever."
|
|
18
|
+
)
|
|
16
19
|
# Registering arguments will automatically add their description to the help menu
|
|
17
20
|
Script.registerArgument("Site: Name of the Site")
|
|
18
21
|
Script.registerArgument("Comment: Reason of the action")
|
|
@@ -32,9 +35,12 @@ def main():
|
|
|
32
35
|
Script.showHelp()
|
|
33
36
|
|
|
34
37
|
email = True
|
|
38
|
+
days = 1
|
|
35
39
|
for switch in Script.getUnprocessedSwitches():
|
|
36
40
|
if switch[0] == "email":
|
|
37
41
|
email = getBoolean(switch[1])
|
|
42
|
+
if switch[0] == "days":
|
|
43
|
+
days = int(switch[1])
|
|
38
44
|
|
|
39
45
|
diracAdmin = DiracAdmin()
|
|
40
46
|
exitCode = 0
|
|
@@ -50,7 +56,7 @@ def main():
|
|
|
50
56
|
|
|
51
57
|
# parseCommandLine show help when mandatory arguments are not specified or incorrect argument
|
|
52
58
|
site, comment = Script.getPositionalArgs(group=True)
|
|
53
|
-
result = diracAdmin.banSite(site, comment, printOutput=True)
|
|
59
|
+
result = diracAdmin.banSite(site, comment, printOutput=True, days=days)
|
|
54
60
|
if not result["OK"]:
|
|
55
61
|
errorList.append((site, result["Message"]))
|
|
56
62
|
exitCode = 2
|
|
@@ -30,6 +30,8 @@ class WMSHistory(BaseType):
|
|
|
30
30
|
"MinorStatus",
|
|
31
31
|
"ApplicationStatus",
|
|
32
32
|
"JobSplitType",
|
|
33
|
+
"Tier",
|
|
34
|
+
"Type",
|
|
33
35
|
]
|
|
34
36
|
|
|
35
37
|
self.monitoringFields = ["Jobs", "Reschedules"]
|
|
@@ -46,6 +48,8 @@ class WMSHistory(BaseType):
|
|
|
46
48
|
"User": {"type": "keyword"},
|
|
47
49
|
"JobGroup": {"type": "keyword"},
|
|
48
50
|
"UserGroup": {"type": "keyword"},
|
|
51
|
+
"Tier": {"type": "keyword"},
|
|
52
|
+
"Type": {"type": "keyword"},
|
|
49
53
|
}
|
|
50
54
|
)
|
|
51
55
|
# {'timestamp': {'type': 'date'}} will be added for all monitoring types
|
|
@@ -447,26 +447,6 @@ class MonitoringDB(ElasticDB):
|
|
|
447
447
|
records.append({paramName: getattr(resObj["_source"], paramName) for paramName in paramNames})
|
|
448
448
|
return S_OK(records)
|
|
449
449
|
|
|
450
|
-
def getLastDayData(self, typeName, condDict):
|
|
451
|
-
"""
|
|
452
|
-
It returns the last day data for a given monitoring type.
|
|
453
|
-
|
|
454
|
-
:returns: for example
|
|
455
|
-
|
|
456
|
-
.. code-block:: python
|
|
457
|
-
|
|
458
|
-
{'sort': [{'timestamp': {'order': 'desc'}}],
|
|
459
|
-
'query': {'bool': {'must': [{'match': {'host': 'dzmathe.cern.ch'}},
|
|
460
|
-
{'match': {'component': 'Bookkeeping_BookkeepingManager'}}]}}}
|
|
461
|
-
|
|
462
|
-
:param str typeName: name of the monitoring type
|
|
463
|
-
:param dict condDict: conditions for the query
|
|
464
|
-
|
|
465
|
-
* key -> name of the field
|
|
466
|
-
* value -> list of possible values
|
|
467
|
-
"""
|
|
468
|
-
return self.__getRawData(typeName, condDict)
|
|
469
|
-
|
|
470
450
|
def getLimitedData(self, typeName, condDict, size=10):
|
|
471
451
|
"""
|
|
472
452
|
Returns a list of records for a given selection.
|
|
@@ -244,24 +244,6 @@ class MonitoringHandlerMixin:
|
|
|
244
244
|
reportRequest["generatePlot"] = False
|
|
245
245
|
return reporter.generate(reportRequest)
|
|
246
246
|
|
|
247
|
-
types_addMonitoringRecords = [str, list]
|
|
248
|
-
|
|
249
|
-
def export_addMonitoringRecords(self, monitoringtype, data):
|
|
250
|
-
"""
|
|
251
|
-
Bulk insert data directly to the given monitoring type.
|
|
252
|
-
|
|
253
|
-
:param str monitoringtype: monitoring type name
|
|
254
|
-
:param list data: list of documents
|
|
255
|
-
:returns: S_OK or S_ERROR
|
|
256
|
-
"""
|
|
257
|
-
|
|
258
|
-
retVal = self.__db.getIndexName(monitoringtype)
|
|
259
|
-
if not retVal["OK"]:
|
|
260
|
-
return retVal
|
|
261
|
-
prefix = retVal["Value"]
|
|
262
|
-
gLogger.debug("addMonitoringRecords:", prefix)
|
|
263
|
-
return self.__db.bulk_index(prefix, data)
|
|
264
|
-
|
|
265
247
|
types_addRecords = [str, str, list]
|
|
266
248
|
|
|
267
249
|
def export_addRecords(self, indexname, monitoringType, data):
|
|
@@ -290,21 +272,6 @@ class MonitoringHandlerMixin:
|
|
|
290
272
|
gLogger.debug("delete index:", indexName)
|
|
291
273
|
return self.__db.deleteIndex(indexName)
|
|
292
274
|
|
|
293
|
-
types_getLastDayData = [str, dict]
|
|
294
|
-
|
|
295
|
-
def export_getLastDayData(self, typeName, condDict):
|
|
296
|
-
"""
|
|
297
|
-
It returns the data from the last day index. Note: we create daily indexes.
|
|
298
|
-
|
|
299
|
-
:param str typeName: name of the monitoring type
|
|
300
|
-
:param dict condDict: conditions for the query
|
|
301
|
-
|
|
302
|
-
* key -> name of the field
|
|
303
|
-
* value -> list of possible values
|
|
304
|
-
"""
|
|
305
|
-
|
|
306
|
-
return self.__db.getLastDayData(typeName, condDict)
|
|
307
|
-
|
|
308
275
|
types_getLimitedDat = [str, dict, int]
|
|
309
276
|
|
|
310
277
|
def export_getLimitedData(self, typeName, condDict, size):
|
|
@@ -6,7 +6,6 @@ from DIRAC import S_ERROR, S_OK
|
|
|
6
6
|
from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations
|
|
7
7
|
from DIRAC.ConfigurationSystem.Client.Helpers.Resources import getSites
|
|
8
8
|
from DIRAC.Core.DISET.RequestHandler import RequestHandler
|
|
9
|
-
from DIRAC.Core.Utilities.JEncode import strToIntDict
|
|
10
9
|
from DIRAC.Core.Utilities.ObjectLoader import ObjectLoader
|
|
11
10
|
from DIRAC.RequestManagementSystem.Client.Operation import Operation
|
|
12
11
|
from DIRAC.RequestManagementSystem.Client.Request import Request
|
|
@@ -334,6 +333,74 @@ class WebAppHandler(RequestHandler):
|
|
|
334
333
|
|
|
335
334
|
return S_OK(resultDict)
|
|
336
335
|
|
|
336
|
+
types_getApplicationStates = []
|
|
337
|
+
|
|
338
|
+
@classmethod
|
|
339
|
+
def export_getApplicationStates(cls, condDict=None, older=None, newer=None):
|
|
340
|
+
"""Return Distinct Values of ApplicationStatus job Attribute in WMS"""
|
|
341
|
+
return cls.jobDB.getDistinctJobAttributes("ApplicationStatus", condDict, older, newer)
|
|
342
|
+
|
|
343
|
+
types_getJobTypes = []
|
|
344
|
+
|
|
345
|
+
@classmethod
|
|
346
|
+
def export_getJobTypes(cls, condDict=None, older=None, newer=None):
|
|
347
|
+
"""Return Distinct Values of JobType job Attribute in WMS"""
|
|
348
|
+
return cls.jobDB.getDistinctJobAttributes("JobType", condDict, older, newer)
|
|
349
|
+
|
|
350
|
+
types_getOwners = []
|
|
351
|
+
|
|
352
|
+
@classmethod
|
|
353
|
+
def export_getOwners(cls, condDict=None, older=None, newer=None):
|
|
354
|
+
"""
|
|
355
|
+
Return Distinct Values of Owner job Attribute in WMS
|
|
356
|
+
"""
|
|
357
|
+
return cls.jobDB.getDistinctJobAttributes("Owner", condDict, older, newer)
|
|
358
|
+
|
|
359
|
+
types_getOwnerGroup = []
|
|
360
|
+
|
|
361
|
+
@classmethod
|
|
362
|
+
def export_getOwnerGroup(cls):
|
|
363
|
+
"""
|
|
364
|
+
Return Distinct Values of OwnerGroup from the JobDB
|
|
365
|
+
"""
|
|
366
|
+
return cls.jobDB.getDistinctJobAttributes("OwnerGroup")
|
|
367
|
+
|
|
368
|
+
types_getJobGroups = []
|
|
369
|
+
|
|
370
|
+
@classmethod
|
|
371
|
+
def export_getJobGroups(cls, condDict=None, older=None, cutDate=None):
|
|
372
|
+
"""
|
|
373
|
+
Return Distinct Values of ProductionId job Attribute in WMS
|
|
374
|
+
"""
|
|
375
|
+
return cls.jobDB.getDistinctJobAttributes("JobGroup", condDict, older, newer=cutDate)
|
|
376
|
+
|
|
377
|
+
types_getSites = []
|
|
378
|
+
|
|
379
|
+
@classmethod
|
|
380
|
+
def export_getSites(cls, condDict=None, older=None, newer=None):
|
|
381
|
+
"""
|
|
382
|
+
Return Distinct Values of Site job Attribute in WMS
|
|
383
|
+
"""
|
|
384
|
+
return cls.jobDB.getDistinctJobAttributes("Site", condDict, older, newer)
|
|
385
|
+
|
|
386
|
+
types_getStates = []
|
|
387
|
+
|
|
388
|
+
@classmethod
|
|
389
|
+
def export_getStates(cls, condDict=None, older=None, newer=None):
|
|
390
|
+
"""
|
|
391
|
+
Return Distinct Values of Status job Attribute in WMS
|
|
392
|
+
"""
|
|
393
|
+
return cls.jobDB.getDistinctJobAttributes("Status", condDict, older, newer)
|
|
394
|
+
|
|
395
|
+
types_getMinorStates = []
|
|
396
|
+
|
|
397
|
+
@classmethod
|
|
398
|
+
def export_getMinorStates(cls, condDict=None, older=None, newer=None):
|
|
399
|
+
"""
|
|
400
|
+
Return Distinct Values of Minor Status job Attribute in WMS
|
|
401
|
+
"""
|
|
402
|
+
return cls.jobDB.getDistinctJobAttributes("MinorStatus", condDict, older, newer)
|
|
403
|
+
|
|
337
404
|
##############################################################################
|
|
338
405
|
# Transformations
|
|
339
406
|
##############################################################################
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""SiteStatus helper
|
|
2
2
|
|
|
3
3
|
Module that acts as a helper for knowing the status of a site.
|
|
4
4
|
It takes care of switching between the CS and the RSS.
|
|
@@ -195,7 +195,7 @@ class SiteStatus(metaclass=DIRACSingleton):
|
|
|
195
195
|
|
|
196
196
|
return S_OK(siteList)
|
|
197
197
|
|
|
198
|
-
def setSiteStatus(self, site, status, comment="No comment"):
|
|
198
|
+
def setSiteStatus(self, site, status, comment="No comment", expiry=None):
|
|
199
199
|
"""
|
|
200
200
|
Set the status of a site in the 'SiteStatus' table of RSS
|
|
201
201
|
|
|
@@ -231,6 +231,8 @@ class SiteStatus(metaclass=DIRACSingleton):
|
|
|
231
231
|
return S_ERROR(f"Unable to get user proxy info {result['Message']} ")
|
|
232
232
|
|
|
233
233
|
tokenExpiration = datetime.utcnow() + timedelta(days=1)
|
|
234
|
+
if expiry:
|
|
235
|
+
tokenExpiration = expiry
|
|
234
236
|
|
|
235
237
|
self.rssCache.acquireLock()
|
|
236
238
|
try:
|
|
@@ -3,11 +3,10 @@ Module containing functions interacting with the CS and useful for the RSS
|
|
|
3
3
|
modules.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from DIRAC import gConfig, gLogger
|
|
6
|
+
from DIRAC import S_OK, gConfig, gLogger
|
|
7
|
+
from DIRAC.ConfigurationSystem.Client.Helpers.Resources import getQueues
|
|
7
8
|
from DIRAC.Core.Utilities.SiteSEMapping import getSEParameters
|
|
8
|
-
from DIRAC.ConfigurationSystem.Client.Helpers.Resources import getQueues, getCESiteMapping
|
|
9
9
|
from DIRAC.DataManagementSystem.Utilities.DMSHelpers import DMSHelpers
|
|
10
|
-
from DIRAC.ResourceStatusSystem.Utilities import Utils
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
def warmUp():
|
|
@@ -19,28 +18,6 @@ def warmUp():
|
|
|
19
18
|
gRefresher.refreshConfigurationIfNeeded()
|
|
20
19
|
|
|
21
20
|
|
|
22
|
-
def getResources():
|
|
23
|
-
"""
|
|
24
|
-
Gets all resources
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
resources = DMSHelpers().getStorageElements()
|
|
28
|
-
|
|
29
|
-
fts = getFTS()
|
|
30
|
-
if fts["OK"]:
|
|
31
|
-
resources = resources + fts["Value"]
|
|
32
|
-
|
|
33
|
-
fc = getFileCatalogs()
|
|
34
|
-
if fc["OK"]:
|
|
35
|
-
resources = resources + fc["Value"]
|
|
36
|
-
|
|
37
|
-
res = getCESiteMapping()
|
|
38
|
-
if res["OK"]:
|
|
39
|
-
resources = resources + list(res["Value"])
|
|
40
|
-
|
|
41
|
-
return S_OK(resources)
|
|
42
|
-
|
|
43
|
-
|
|
44
21
|
def getStorageElementEndpoint(seName):
|
|
45
22
|
"""Get endpoints of a StorageElement
|
|
46
23
|
|
|
@@ -86,12 +63,6 @@ def getFTS():
|
|
|
86
63
|
return S_OK([])
|
|
87
64
|
|
|
88
65
|
|
|
89
|
-
def getSpaceTokenEndpoints():
|
|
90
|
-
"""Get Space Token Endpoints"""
|
|
91
|
-
|
|
92
|
-
return Utils.getCSTree("Shares/Disk")
|
|
93
|
-
|
|
94
|
-
|
|
95
66
|
def getFileCatalogs():
|
|
96
67
|
"""
|
|
97
68
|
Gets all storage elements from /Resources/FileCatalogs
|
|
@@ -29,6 +29,7 @@ def registerSwitches():
|
|
|
29
29
|
("reason=", "Reason to set the Status"),
|
|
30
30
|
("VO=", "VO to change a status for. When omitted, status will be changed for all VOs"),
|
|
31
31
|
("tokenOwner=", "Owner of the token"),
|
|
32
|
+
("days=", "Number of days the token is valid for. Default is 1 day. 0 or less days denotes forever."),
|
|
32
33
|
)
|
|
33
34
|
|
|
34
35
|
for switch in switches:
|
|
@@ -50,6 +51,7 @@ def parseSwitches():
|
|
|
50
51
|
switches = dict(Script.getUnprocessedSwitches())
|
|
51
52
|
switches.setdefault("statusType", None)
|
|
52
53
|
switches.setdefault("VO", None)
|
|
54
|
+
switches.setdefault("days", 1)
|
|
53
55
|
|
|
54
56
|
for key in ("element", "name", "status", "reason"):
|
|
55
57
|
if key not in switches:
|
|
@@ -183,7 +185,11 @@ def setStatus(switchDict, tokenOwner):
|
|
|
183
185
|
)
|
|
184
186
|
return S_OK()
|
|
185
187
|
|
|
186
|
-
|
|
188
|
+
tokenLifetime = int(switchDict["days"])
|
|
189
|
+
if tokenLifetime <= 0:
|
|
190
|
+
tokenExpiration = datetime.max
|
|
191
|
+
else:
|
|
192
|
+
tokenExpiration = datetime.utcnow().replace(microsecond=0) + timedelta(days=tokenLifetime)
|
|
187
193
|
|
|
188
194
|
for status, statusType in elements:
|
|
189
195
|
gLogger.debug(f"{status} {statusType}")
|
|
@@ -193,8 +199,16 @@ def setStatus(switchDict, tokenOwner):
|
|
|
193
199
|
continue
|
|
194
200
|
|
|
195
201
|
gLogger.debug(
|
|
196
|
-
"About to set status %s -> %s for %s, statusType: %s, VO: %s, reason: %s"
|
|
197
|
-
% (
|
|
202
|
+
"About to set status %s -> %s for %s, statusType: %s, VO: %s, reason: %s, days: %s"
|
|
203
|
+
% (
|
|
204
|
+
status,
|
|
205
|
+
switchDict["status"],
|
|
206
|
+
switchDict["name"],
|
|
207
|
+
statusType,
|
|
208
|
+
switchDict["VO"],
|
|
209
|
+
switchDict["reason"],
|
|
210
|
+
switchDict["days"],
|
|
211
|
+
)
|
|
198
212
|
)
|
|
199
213
|
result = rssClient.modifyStatusElement(
|
|
200
214
|
switchDict["element"],
|
|
@@ -205,7 +219,7 @@ def setStatus(switchDict, tokenOwner):
|
|
|
205
219
|
reason=switchDict["reason"],
|
|
206
220
|
vO=switchDict["VO"],
|
|
207
221
|
tokenOwner=tokenOwner,
|
|
208
|
-
tokenExpiration=
|
|
222
|
+
tokenExpiration=tokenExpiration,
|
|
209
223
|
)
|
|
210
224
|
if not result["OK"]:
|
|
211
225
|
return result
|