DIRAC 9.0.0a42__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.
- 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/CSGlobals.py +0 -9
- DIRAC/ConfigurationSystem/Client/Helpers/Registry.py +38 -26
- DIRAC/ConfigurationSystem/Client/Helpers/Resources.py +11 -43
- DIRAC/ConfigurationSystem/Client/Helpers/test/Test_Helpers.py +0 -16
- DIRAC/ConfigurationSystem/Client/LocalConfiguration.py +14 -8
- DIRAC/ConfigurationSystem/Client/PathFinder.py +47 -8
- DIRAC/ConfigurationSystem/Client/SyncPlugins/CERNLDAPSyncPlugin.py +4 -1
- DIRAC/ConfigurationSystem/Client/VOMS2CSSynchronizer.py +32 -19
- DIRAC/ConfigurationSystem/Client/test/Test_PathFinder.py +41 -1
- DIRAC/ConfigurationSystem/private/RefresherBase.py +4 -2
- DIRAC/Core/Base/API.py +4 -7
- DIRAC/Core/Base/SQLAlchemyDB.py +1 -0
- DIRAC/Core/DISET/ServiceReactor.py +11 -3
- DIRAC/Core/DISET/private/BaseClient.py +1 -2
- DIRAC/Core/DISET/private/Transports/M2SSLTransport.py +9 -7
- DIRAC/Core/DISET/private/Transports/SSL/M2Utils.py +3 -1
- DIRAC/Core/LCG/GOCDBClient.py +5 -7
- DIRAC/Core/Security/DiracX.py +31 -17
- DIRAC/Core/Security/IAMService.py +5 -10
- DIRAC/Core/Security/Locations.py +27 -18
- DIRAC/Core/Security/ProxyInfo.py +9 -5
- DIRAC/Core/Security/VOMSService.py +2 -4
- DIRAC/Core/Security/m2crypto/X509Certificate.py +4 -6
- DIRAC/Core/Security/m2crypto/asn1_utils.py +17 -5
- DIRAC/Core/Security/test/test_diracx_token_from_pem.py +161 -0
- DIRAC/Core/Tornado/Client/ClientSelector.py +4 -1
- DIRAC/Core/Tornado/Server/TornadoService.py +1 -1
- DIRAC/Core/Utilities/CGroups2.py +328 -0
- DIRAC/Core/Utilities/ClassAd/ClassAdLight.py +4 -290
- DIRAC/Core/Utilities/DErrno.py +5 -309
- DIRAC/Core/Utilities/Extensions.py +10 -1
- DIRAC/Core/Utilities/File.py +1 -1
- DIRAC/Core/Utilities/Graphs/GraphData.py +1 -1
- DIRAC/Core/Utilities/Graphs/GraphUtilities.py +6 -1
- DIRAC/Core/Utilities/JDL.py +1 -195
- DIRAC/Core/Utilities/List.py +1 -124
- DIRAC/Core/Utilities/MySQL.py +103 -99
- DIRAC/Core/Utilities/Os.py +32 -1
- DIRAC/Core/Utilities/Platform.py +2 -107
- DIRAC/Core/Utilities/Proxy.py +0 -4
- DIRAC/Core/Utilities/ReturnValues.py +7 -252
- DIRAC/Core/Utilities/StateMachine.py +12 -178
- DIRAC/Core/Utilities/Subprocess.py +35 -14
- DIRAC/Core/Utilities/TimeUtilities.py +10 -253
- DIRAC/Core/Utilities/test/Test_JDL.py +0 -3
- DIRAC/Core/Utilities/test/Test_Profiler.py +20 -20
- DIRAC/Core/scripts/dirac_agent.py +1 -1
- DIRAC/Core/scripts/dirac_apptainer_exec.py +72 -46
- DIRAC/Core/scripts/dirac_configure.py +1 -3
- DIRAC/Core/scripts/dirac_install_db.py +24 -6
- DIRAC/Core/scripts/dirac_platform.py +1 -92
- DIRAC/DataManagementSystem/Agent/FTS3Agent.py +8 -7
- DIRAC/DataManagementSystem/Agent/RequestOperations/RemoveFile.py +7 -6
- DIRAC/DataManagementSystem/Client/FTS3Job.py +71 -34
- DIRAC/DataManagementSystem/DB/FTS3DB.py +7 -3
- DIRAC/DataManagementSystem/DB/FileCatalogComponents/DatasetManager/DatasetManager.py +1 -1
- DIRAC/DataManagementSystem/DB/FileCatalogDB.sql +9 -9
- DIRAC/DataManagementSystem/DB/FileCatalogWithFkAndPsDB.sql +9 -9
- DIRAC/DataManagementSystem/Utilities/DMSHelpers.py +6 -2
- DIRAC/DataManagementSystem/scripts/dirac_admin_allow_se.py +13 -8
- DIRAC/DataManagementSystem/scripts/dirac_admin_ban_se.py +13 -8
- DIRAC/DataManagementSystem/scripts/dirac_dms_create_moving_request.py +2 -0
- DIRAC/DataManagementSystem/scripts/dirac_dms_protocol_matrix.py +0 -1
- DIRAC/FrameworkSystem/Client/BundleDeliveryClient.py +2 -7
- DIRAC/FrameworkSystem/Client/ComponentInstaller.py +9 -4
- DIRAC/FrameworkSystem/Client/ProxyManagerClient.py +5 -2
- DIRAC/FrameworkSystem/Client/SystemAdministratorClientCLI.py +11 -6
- DIRAC/FrameworkSystem/ConfigTemplate.cfg +2 -0
- DIRAC/FrameworkSystem/DB/AuthDB.py +3 -3
- DIRAC/FrameworkSystem/DB/InstalledComponentsDB.py +4 -4
- DIRAC/FrameworkSystem/DB/ProxyDB.py +11 -3
- DIRAC/FrameworkSystem/DB/TokenDB.py +1 -1
- DIRAC/FrameworkSystem/Service/ProxyManagerHandler.py +8 -6
- DIRAC/FrameworkSystem/Utilities/MonitoringUtilities.py +2 -19
- DIRAC/FrameworkSystem/Utilities/TokenManagementUtilities.py +3 -2
- DIRAC/FrameworkSystem/Utilities/diracx.py +36 -14
- DIRAC/FrameworkSystem/private/authorization/AuthServer.py +2 -2
- DIRAC/FrameworkSystem/scripts/dirac_admin_update_pilot.py +18 -11
- DIRAC/FrameworkSystem/scripts/dirac_login.py +2 -2
- DIRAC/FrameworkSystem/scripts/dirac_proxy_init.py +7 -8
- DIRAC/Interfaces/API/Dirac.py +27 -15
- DIRAC/Interfaces/API/DiracAdmin.py +45 -17
- DIRAC/Interfaces/API/Job.py +9 -13
- DIRAC/Interfaces/scripts/dirac_admin_allow_site.py +12 -18
- DIRAC/Interfaces/scripts/dirac_admin_ban_site.py +12 -10
- DIRAC/Interfaces/scripts/dirac_admin_get_site_mask.py +4 -13
- DIRAC/Interfaces/scripts/dirac_admin_reset_job.py +3 -6
- DIRAC/Interfaces/scripts/dirac_wms_job_parameters.py +0 -1
- DIRAC/MonitoringSystem/Client/Types/WMSHistory.py +4 -0
- DIRAC/MonitoringSystem/Client/WebAppClient.py +26 -0
- DIRAC/MonitoringSystem/ConfigTemplate.cfg +9 -0
- DIRAC/MonitoringSystem/DB/MonitoringDB.py +6 -25
- DIRAC/MonitoringSystem/Service/MonitoringHandler.py +0 -33
- DIRAC/MonitoringSystem/Service/WebAppHandler.py +599 -0
- DIRAC/MonitoringSystem/private/MainReporter.py +0 -3
- DIRAC/ProductionSystem/DB/ProductionDB.sql +4 -4
- DIRAC/ProductionSystem/scripts/dirac_prod_get.py +2 -2
- DIRAC/ProductionSystem/scripts/dirac_prod_get_all.py +2 -2
- DIRAC/ProductionSystem/scripts/dirac_prod_get_trans.py +2 -3
- DIRAC/RequestManagementSystem/Agent/RequestExecutingAgent.py +8 -6
- DIRAC/RequestManagementSystem/Agent/RequestOperations/ForwardDISET.py +2 -14
- DIRAC/RequestManagementSystem/Client/ReqClient.py +66 -13
- DIRAC/RequestManagementSystem/ConfigTemplate.cfg +6 -6
- DIRAC/RequestManagementSystem/DB/RequestDB.py +10 -5
- DIRAC/RequestManagementSystem/DB/test/RMSTestScenari.py +2 -0
- DIRAC/RequestManagementSystem/private/RequestValidator.py +40 -46
- DIRAC/ResourceStatusSystem/Client/SiteStatus.py +4 -2
- DIRAC/ResourceStatusSystem/Command/FreeDiskSpaceCommand.py +3 -1
- DIRAC/ResourceStatusSystem/DB/ResourceManagementDB.py +8 -8
- DIRAC/ResourceStatusSystem/DB/ResourceStatusDB.py +2 -2
- DIRAC/ResourceStatusSystem/Utilities/CSHelpers.py +2 -31
- DIRAC/ResourceStatusSystem/scripts/dirac_rss_set_status.py +30 -12
- DIRAC/Resources/Catalog/RucioFileCatalogClient.py +195 -1
- DIRAC/Resources/Catalog/test/Test_RucioFileCatalogClient.py +181 -0
- DIRAC/Resources/Computing/AREXComputingElement.py +25 -8
- DIRAC/Resources/Computing/BatchSystems/Condor.py +126 -108
- DIRAC/Resources/Computing/BatchSystems/SLURM.py +5 -1
- DIRAC/Resources/Computing/BatchSystems/test/Test_SLURM.py +46 -0
- DIRAC/Resources/Computing/ComputingElement.py +1 -1
- DIRAC/Resources/Computing/HTCondorCEComputingElement.py +44 -44
- DIRAC/Resources/Computing/InProcessComputingElement.py +4 -2
- DIRAC/Resources/Computing/LocalComputingElement.py +1 -18
- DIRAC/Resources/Computing/SSHBatchComputingElement.py +1 -17
- DIRAC/Resources/Computing/SSHComputingElement.py +1 -18
- DIRAC/Resources/Computing/SingularityComputingElement.py +19 -5
- DIRAC/Resources/Computing/test/Test_HTCondorCEComputingElement.py +67 -49
- DIRAC/Resources/Computing/test/Test_PoolComputingElement.py +2 -1
- DIRAC/Resources/IdProvider/CheckInIdProvider.py +13 -0
- DIRAC/Resources/IdProvider/IdProviderFactory.py +11 -3
- DIRAC/Resources/MessageQueue/StompMQConnector.py +1 -1
- DIRAC/Resources/Storage/GFAL2_StorageBase.py +24 -15
- DIRAC/Resources/Storage/OccupancyPlugins/WLCGAccountingHTTPJson.py +1 -3
- DIRAC/Resources/Storage/StorageBase.py +4 -2
- DIRAC/Resources/Storage/StorageElement.py +6 -7
- DIRAC/StorageManagementSystem/DB/StorageManagementDB.sql +2 -2
- DIRAC/TransformationSystem/Agent/TaskManagerAgentBase.py +10 -16
- DIRAC/TransformationSystem/Agent/TransformationAgent.py +22 -1
- DIRAC/TransformationSystem/Agent/TransformationCleaningAgent.py +16 -16
- DIRAC/TransformationSystem/Client/TaskManager.py +2 -4
- DIRAC/TransformationSystem/Client/Transformation.py +6 -7
- DIRAC/TransformationSystem/Client/TransformationClient.py +21 -11
- DIRAC/TransformationSystem/Client/Utilities.py +9 -0
- DIRAC/TransformationSystem/DB/TransformationDB.py +11 -14
- DIRAC/TransformationSystem/DB/TransformationDB.sql +9 -9
- DIRAC/TransformationSystem/Service/TransformationManagerHandler.py +0 -333
- DIRAC/TransformationSystem/Utilities/ReplicationCLIParameters.py +3 -3
- DIRAC/TransformationSystem/Utilities/TransformationInfo.py +7 -5
- DIRAC/TransformationSystem/scripts/dirac_production_runjoblocal.py +2 -4
- DIRAC/TransformationSystem/test/Test_TransformationInfo.py +22 -15
- DIRAC/TransformationSystem/test/Test_replicationTransformation.py +5 -6
- DIRAC/Workflow/Modules/test/Test_Modules.py +5 -0
- DIRAC/WorkloadManagementSystem/Agent/JobAgent.py +38 -26
- DIRAC/WorkloadManagementSystem/Agent/JobCleaningAgent.py +12 -8
- DIRAC/WorkloadManagementSystem/Agent/PilotSyncAgent.py +4 -3
- DIRAC/WorkloadManagementSystem/Agent/PushJobAgent.py +13 -13
- DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py +18 -14
- DIRAC/WorkloadManagementSystem/Agent/StalledJobAgent.py +18 -51
- DIRAC/WorkloadManagementSystem/Agent/StatesAccountingAgent.py +41 -1
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobAgent.py +45 -4
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobCleaningAgent.py +7 -9
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PushJobAgent.py +1 -0
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_SiteDirector.py +9 -2
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_StalledJobAgent.py +4 -5
- DIRAC/WorkloadManagementSystem/Client/DownloadInputData.py +9 -9
- DIRAC/WorkloadManagementSystem/Client/InputDataResolution.py +6 -6
- DIRAC/WorkloadManagementSystem/Client/JobMonitoringClient.py +10 -11
- DIRAC/WorkloadManagementSystem/Client/JobReport.py +1 -1
- DIRAC/WorkloadManagementSystem/Client/JobState/CachedJobState.py +3 -0
- DIRAC/WorkloadManagementSystem/Client/JobState/JobManifest.py +32 -261
- DIRAC/WorkloadManagementSystem/Client/JobState/JobState.py +6 -0
- DIRAC/WorkloadManagementSystem/Client/JobStateUpdateClient.py +3 -0
- DIRAC/WorkloadManagementSystem/Client/JobStatus.py +8 -152
- DIRAC/WorkloadManagementSystem/Client/PoolXMLSlice.py +12 -19
- DIRAC/WorkloadManagementSystem/Client/SandboxStoreClient.py +25 -38
- DIRAC/WorkloadManagementSystem/Client/WMSClient.py +2 -3
- DIRAC/WorkloadManagementSystem/Client/test/Test_Client_DownloadInputData.py +29 -0
- DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg +4 -8
- DIRAC/WorkloadManagementSystem/DB/JobDB.py +89 -132
- DIRAC/WorkloadManagementSystem/DB/JobDB.sql +8 -8
- DIRAC/WorkloadManagementSystem/DB/JobDBUtils.py +18 -147
- DIRAC/WorkloadManagementSystem/DB/JobLoggingDB.py +19 -6
- DIRAC/WorkloadManagementSystem/DB/JobParametersDB.py +9 -9
- DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py +16 -5
- DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.sql +3 -3
- DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py +44 -82
- DIRAC/WorkloadManagementSystem/DB/StatusUtils.py +125 -0
- DIRAC/WorkloadManagementSystem/DB/tests/Test_JobDB.py +1 -1
- DIRAC/WorkloadManagementSystem/DB/tests/Test_StatusUtils.py +28 -0
- DIRAC/WorkloadManagementSystem/Executor/JobSanity.py +5 -4
- DIRAC/WorkloadManagementSystem/Executor/JobScheduling.py +4 -0
- DIRAC/WorkloadManagementSystem/FutureClient/JobStateUpdateClient.py +75 -33
- DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapper.py +22 -11
- DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapperTemplate.py +9 -10
- DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapper.py +60 -10
- DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapperTemplate.py +4 -0
- DIRAC/WorkloadManagementSystem/Service/JobManagerHandler.py +33 -154
- DIRAC/WorkloadManagementSystem/Service/JobMonitoringHandler.py +5 -323
- DIRAC/WorkloadManagementSystem/Service/JobStateUpdateHandler.py +0 -16
- DIRAC/WorkloadManagementSystem/Service/PilotManagerHandler.py +6 -103
- DIRAC/WorkloadManagementSystem/Service/SandboxStoreHandler.py +7 -53
- DIRAC/WorkloadManagementSystem/Service/WMSAdministratorHandler.py +16 -79
- DIRAC/WorkloadManagementSystem/Service/WMSUtilities.py +4 -18
- DIRAC/WorkloadManagementSystem/Utilities/JobModel.py +28 -209
- DIRAC/WorkloadManagementSystem/Utilities/JobParameters.py +65 -3
- DIRAC/WorkloadManagementSystem/Utilities/JobStatusUtility.py +2 -64
- DIRAC/WorkloadManagementSystem/Utilities/ParametricJob.py +7 -171
- DIRAC/WorkloadManagementSystem/Utilities/PilotCStoJSONSynchronizer.py +73 -7
- DIRAC/WorkloadManagementSystem/Utilities/PilotWrapper.py +41 -11
- DIRAC/WorkloadManagementSystem/Utilities/RemoteRunner.py +16 -0
- DIRAC/WorkloadManagementSystem/Utilities/Utils.py +36 -1
- DIRAC/WorkloadManagementSystem/Utilities/jobAdministration.py +15 -0
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobModel.py +1 -15
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_ParametricJob.py +45 -128
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_PilotWrapper.py +16 -0
- DIRAC/WorkloadManagementSystem/scripts/dirac_jobexec.py +7 -2
- DIRAC/WorkloadManagementSystem/scripts/dirac_wms_pilot_job_info.py +1 -1
- DIRAC/__init__.py +62 -60
- DIRAC/tests/Utilities/testJobDefinitions.py +22 -28
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/METADATA +8 -5
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/RECORD +229 -228
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/WHEEL +1 -1
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/entry_points.txt +0 -3
- DIRAC/Core/Utilities/test/Test_List.py +0 -150
- DIRAC/Core/Utilities/test/Test_Time.py +0 -88
- DIRAC/Resources/Computing/PilotBundle.py +0 -70
- DIRAC/TransformationSystem/scripts/dirac_transformation_archive.py +0 -30
- DIRAC/TransformationSystem/scripts/dirac_transformation_clean.py +0 -30
- DIRAC/TransformationSystem/scripts/dirac_transformation_remove_output.py +0 -30
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobManager.py +0 -58
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info/licenses}/LICENSE +0 -0
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/top_level.txt +0 -0
|
@@ -11,8 +11,11 @@ The following options can be set in ``Systems/WorkloadManagement/Databases/JobDB
|
|
|
11
11
|
* *CompressJDLs*: Enable compression of JDLs when they are stored in the database, default *False*.
|
|
12
12
|
|
|
13
13
|
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
14
16
|
import datetime
|
|
15
17
|
import operator
|
|
18
|
+
from typing import overload
|
|
16
19
|
|
|
17
20
|
from DIRAC.ConfigurationSystem.Client.Helpers.Registry import getVOForGroup
|
|
18
21
|
from DIRAC.ConfigurationSystem.Client.Helpers.Resources import getSiteTier
|
|
@@ -20,7 +23,14 @@ from DIRAC.Core.Base.DB import DB
|
|
|
20
23
|
from DIRAC.Core.Utilities.ClassAd.ClassAdLight import ClassAd
|
|
21
24
|
from DIRAC.Core.Utilities.Decorators import deprecated
|
|
22
25
|
from DIRAC.Core.Utilities.DErrno import EWMSJMAN, EWMSSUBM, cmpError
|
|
23
|
-
from DIRAC.Core.Utilities.ReturnValues import
|
|
26
|
+
from DIRAC.Core.Utilities.ReturnValues import (
|
|
27
|
+
S_ERROR,
|
|
28
|
+
S_OK,
|
|
29
|
+
convertToReturnValue,
|
|
30
|
+
returnValueOrRaise,
|
|
31
|
+
SErrorException,
|
|
32
|
+
DReturnType,
|
|
33
|
+
)
|
|
24
34
|
from DIRAC.FrameworkSystem.Client.Logger import contextLogger
|
|
25
35
|
from DIRAC.ResourceStatusSystem.Client.SiteStatus import SiteStatus
|
|
26
36
|
from DIRAC.WorkloadManagementSystem.Client import JobMinorStatus, JobStatus
|
|
@@ -106,18 +116,7 @@ class JobDB(DB):
|
|
|
106
116
|
Returns a dictionary with the Job Parameters.
|
|
107
117
|
If parameterList is empty - all the parameters are returned.
|
|
108
118
|
"""
|
|
109
|
-
|
|
110
|
-
if isinstance(jobID, (str, int)):
|
|
111
|
-
jobID = [jobID]
|
|
112
|
-
|
|
113
|
-
jobIDList = []
|
|
114
|
-
for jID in jobID:
|
|
115
|
-
ret = self._escapeString(str(jID))
|
|
116
|
-
if not ret["OK"]:
|
|
117
|
-
return ret
|
|
118
|
-
jobIDList.append(ret["Value"])
|
|
119
|
-
|
|
120
|
-
# self.log.debug('JobDB.getParameters: Getting Parameters for jobs %s' % ','.join(jobIDList))
|
|
119
|
+
jobIDList = [jobID] if isinstance(jobID, (str, int)) else jobID
|
|
121
120
|
|
|
122
121
|
resultDict = {}
|
|
123
122
|
if paramList:
|
|
@@ -130,7 +129,7 @@ class JobDB(DB):
|
|
|
130
129
|
return ret
|
|
131
130
|
paramNameList.append(ret["Value"])
|
|
132
131
|
cmd = "SELECT JobID, Name, Value FROM JobParameters WHERE JobID IN ({}) AND Name IN ({})".format(
|
|
133
|
-
",".join(jobIDList),
|
|
132
|
+
",".join(str(int(j)) for j in jobIDList),
|
|
134
133
|
",".join(paramNameList),
|
|
135
134
|
)
|
|
136
135
|
result = self._query(cmd)
|
|
@@ -207,13 +206,13 @@ class JobDB(DB):
|
|
|
207
206
|
return S_ERROR("JobDB.getAtticJobParameters: failed to retrieve parameters")
|
|
208
207
|
|
|
209
208
|
#############################################################################
|
|
209
|
+
@convertToReturnValue
|
|
210
210
|
def getJobsAttributes(self, jobIDs, attrList=None):
|
|
211
211
|
"""Get all Job(s) Attributes for a given list of jobIDs.
|
|
212
212
|
Return a dictionary with all Job Attributes as value pairs
|
|
213
213
|
"""
|
|
214
|
-
|
|
215
214
|
if not jobIDs:
|
|
216
|
-
return
|
|
215
|
+
return {}
|
|
217
216
|
|
|
218
217
|
# If no list of attributes is given, return all attributes
|
|
219
218
|
if not attrList:
|
|
@@ -229,28 +228,29 @@ class JobDB(DB):
|
|
|
229
228
|
|
|
230
229
|
attrNameListS = []
|
|
231
230
|
for x in attrList:
|
|
232
|
-
|
|
233
|
-
if not ret["OK"]:
|
|
234
|
-
return ret
|
|
235
|
-
x = "`" + ret["Value"][1:-1] + "`"
|
|
231
|
+
x = "`" + returnValueOrRaise(self._escapeString(x))[1:-1] + "`"
|
|
236
232
|
attrNameListS.append(x)
|
|
237
233
|
attrNames = "JobID," + ",".join(attrNameListS)
|
|
238
234
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
235
|
+
sqlCmd = "CREATE TEMPORARY TABLE to_select_Jobs (JobID INTEGER NOT NULL, PRIMARY KEY (JobID)) ENGINE=MEMORY;"
|
|
236
|
+
returnValueOrRaise(self._update(sqlCmd))
|
|
237
|
+
try:
|
|
238
|
+
sqlCmd = "INSERT INTO to_select_Jobs (JobID) VALUES ( %s )"
|
|
239
|
+
returnValueOrRaise(self._updatemany(sqlCmd, [(int(j),) for j in jobIDs]))
|
|
240
|
+
sqlCmd = f"SELECT {attrNames} FROM Jobs JOIN to_select_Jobs USING (JobID)"
|
|
241
|
+
result = returnValueOrRaise(self._query(sqlCmd))
|
|
242
|
+
finally:
|
|
243
|
+
sqlCmd = "DROP TEMPORARY TABLE to_select_Jobs"
|
|
244
|
+
returnValueOrRaise(self._update(sqlCmd))
|
|
245
245
|
|
|
246
246
|
attributes = {}
|
|
247
|
-
for t_att in
|
|
247
|
+
for t_att in result:
|
|
248
248
|
jobID = int(t_att[0])
|
|
249
249
|
attributes.setdefault(jobID, {})
|
|
250
250
|
for tx, ax in zip(t_att[1:], attrList):
|
|
251
251
|
attributes[jobID].setdefault(ax, tx)
|
|
252
252
|
|
|
253
|
-
return
|
|
253
|
+
return attributes
|
|
254
254
|
|
|
255
255
|
#############################################################################
|
|
256
256
|
def getJobAttributes(self, jobID, attrList=None):
|
|
@@ -330,23 +330,42 @@ class JobDB(DB):
|
|
|
330
330
|
|
|
331
331
|
#############################################################################
|
|
332
332
|
|
|
333
|
-
|
|
333
|
+
@overload
|
|
334
|
+
def getInputData(self, jobID: int | str) -> DReturnType[list[str]]:
|
|
335
|
+
...
|
|
336
|
+
|
|
337
|
+
@overload
|
|
338
|
+
def getInputData(self, jobID: list[int | str]) -> DReturnType[dict[int, list[str]]]:
|
|
339
|
+
...
|
|
340
|
+
|
|
341
|
+
def getInputData(self, jobID: int | str | list[int | str]) -> DReturnType[list[str] | dict[int, list[str]]]:
|
|
334
342
|
"""Get input data for the given job"""
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
343
|
+
if isinstance(jobID, (int, str)):
|
|
344
|
+
ret = self._escapeString(jobID)
|
|
345
|
+
if not ret["OK"]:
|
|
346
|
+
return ret
|
|
347
|
+
jobID = ret["Value"]
|
|
348
|
+
query = f"JobID={jobID}"
|
|
349
|
+
result = []
|
|
350
|
+
else:
|
|
351
|
+
job_ids = {int(i) for i in jobID}
|
|
352
|
+
query = f"JobID IN ({','.join(map(str, job_ids))})"
|
|
353
|
+
result = {i: [] for i in job_ids}
|
|
354
|
+
cmd = f"SELECT JobID, LFN FROM InputData WHERE {query}"
|
|
340
355
|
res = self._query(cmd)
|
|
341
356
|
if not res["OK"]:
|
|
342
357
|
return res
|
|
343
358
|
|
|
344
|
-
|
|
345
|
-
|
|
359
|
+
for jid, lfn in res["Value"]:
|
|
360
|
+
lfn = lfn.strip()
|
|
346
361
|
if lfn.lower().startswith("lfn:"):
|
|
347
|
-
|
|
362
|
+
lfn = lfn[4:]
|
|
363
|
+
if isinstance(result, list):
|
|
364
|
+
result.append(lfn)
|
|
365
|
+
else:
|
|
366
|
+
result[jid].append(lfn)
|
|
348
367
|
|
|
349
|
-
return S_OK(
|
|
368
|
+
return S_OK(result)
|
|
350
369
|
|
|
351
370
|
#############################################################################
|
|
352
371
|
def setInputData(self, jobID, inputData):
|
|
@@ -527,12 +546,10 @@ class JobDB(DB):
|
|
|
527
546
|
if not isinstance(jobID, (list, tuple)):
|
|
528
547
|
jobIDList = [jobID]
|
|
529
548
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
return ret
|
|
535
|
-
jIDList.append(ret["Value"])
|
|
549
|
+
try:
|
|
550
|
+
jIDList = [int(jID) for jID in jobIDList]
|
|
551
|
+
except ValueError as e:
|
|
552
|
+
return S_ERROR(f"JobDB.setAttributes: {e}")
|
|
536
553
|
|
|
537
554
|
if len(attrNames) != len(attrValues):
|
|
538
555
|
return S_ERROR("JobDB.setAttributes: incompatible Argument length")
|
|
@@ -561,7 +578,7 @@ class JobDB(DB):
|
|
|
561
578
|
if not attr:
|
|
562
579
|
return S_ERROR("JobDB.setAttributes: Nothing to do")
|
|
563
580
|
|
|
564
|
-
cmd = f"UPDATE Jobs SET {', '.join(attr)} WHERE JobID in ( {', '.join(jIDList)} )"
|
|
581
|
+
cmd = f"UPDATE Jobs SET {', '.join(attr)} WHERE JobID in ( {', '.join(str(int(j)) for j in jIDList)} )"
|
|
565
582
|
|
|
566
583
|
if myDate:
|
|
567
584
|
cmd += f" AND LastUpdateTime < {myDate}"
|
|
@@ -987,44 +1004,42 @@ class JobDB(DB):
|
|
|
987
1004
|
return S_OK()
|
|
988
1005
|
|
|
989
1006
|
#############################################################################
|
|
1007
|
+
@convertToReturnValue
|
|
990
1008
|
def removeJobFromDB(self, jobIDs):
|
|
991
1009
|
"""
|
|
992
1010
|
Remove jobs from the Job DB and clean up all the job related data in various tables
|
|
993
1011
|
"""
|
|
994
|
-
|
|
995
|
-
# ret = self._escapeString(jobID)
|
|
996
|
-
# if not ret['OK']:
|
|
997
|
-
# return ret
|
|
998
|
-
# e_jobID = ret['Value']
|
|
999
|
-
|
|
1000
1012
|
if not jobIDs:
|
|
1001
|
-
return
|
|
1002
|
-
|
|
1003
|
-
if not isinstance(jobIDs, list):
|
|
1004
|
-
jobIDList = [jobIDs]
|
|
1005
|
-
else:
|
|
1006
|
-
jobIDList = jobIDs
|
|
1013
|
+
return None
|
|
1014
|
+
jobIDList = jobIDs if isinstance(jobIDs, list) else [jobIDs]
|
|
1007
1015
|
|
|
1008
1016
|
failedTablesList = []
|
|
1009
|
-
for table in [
|
|
1010
|
-
"InputData",
|
|
1011
|
-
"JobParameters",
|
|
1012
|
-
"AtticJobParameters",
|
|
1013
|
-
"HeartBeatLoggingInfo",
|
|
1014
|
-
"OptimizerParameters",
|
|
1015
|
-
"JobCommands",
|
|
1016
|
-
"Jobs",
|
|
1017
|
-
"JobJDLs",
|
|
1018
|
-
]:
|
|
1019
|
-
cmd = f"DELETE FROM {table} WHERE JobID in ({','.join(str(j) for j in jobIDList)})"
|
|
1020
|
-
result = self._update(cmd)
|
|
1021
|
-
if not result["OK"]:
|
|
1022
|
-
failedTablesList.append(table)
|
|
1023
1017
|
|
|
1024
|
-
|
|
1025
|
-
|
|
1018
|
+
sqlCmd = "CREATE TEMPORARY TABLE to_delete_Jobs (JobID INT(11) UNSIGNED NOT NULL, PRIMARY KEY (JobID)) ENGINE=MEMORY;"
|
|
1019
|
+
returnValueOrRaise(self._update(sqlCmd))
|
|
1020
|
+
try:
|
|
1021
|
+
sqlCmd = "INSERT INTO to_delete_Jobs (JobID) VALUES ( %s )"
|
|
1022
|
+
returnValueOrRaise(self._updatemany(sqlCmd, [(j,) for j in jobIDList]))
|
|
1023
|
+
|
|
1024
|
+
for table in [
|
|
1025
|
+
"InputData",
|
|
1026
|
+
"JobParameters",
|
|
1027
|
+
"AtticJobParameters",
|
|
1028
|
+
"HeartBeatLoggingInfo",
|
|
1029
|
+
"OptimizerParameters",
|
|
1030
|
+
"JobCommands",
|
|
1031
|
+
"Jobs",
|
|
1032
|
+
"JobJDLs",
|
|
1033
|
+
]:
|
|
1034
|
+
sqlCmd = f"DELETE m from `{table}` m JOIN to_delete_Jobs t USING (JobID)"
|
|
1035
|
+
if not self._update(sqlCmd)["OK"]:
|
|
1036
|
+
failedTablesList.append(table)
|
|
1037
|
+
finally:
|
|
1038
|
+
sqlCmd = "DROP TEMPORARY TABLE to_delete_Jobs"
|
|
1039
|
+
returnValueOrRaise(self._update(sqlCmd))
|
|
1026
1040
|
|
|
1027
|
-
|
|
1041
|
+
if failedTablesList:
|
|
1042
|
+
raise SErrorException(f"Errors while job removal (tables {','.join(failedTablesList)})")
|
|
1028
1043
|
|
|
1029
1044
|
#############################################################################
|
|
1030
1045
|
def rescheduleJob(self, jobID):
|
|
@@ -1175,64 +1190,6 @@ class JobDB(DB):
|
|
|
1175
1190
|
|
|
1176
1191
|
return retVal
|
|
1177
1192
|
|
|
1178
|
-
#############################################################################
|
|
1179
|
-
def getSiteSummary(self):
|
|
1180
|
-
"""Get the summary of jobs in a given status on all the sites"""
|
|
1181
|
-
|
|
1182
|
-
waitingList = ['"Submitted"', '"Assigned"', '"Waiting"', '"Matched"']
|
|
1183
|
-
waitingString = ",".join(waitingList)
|
|
1184
|
-
|
|
1185
|
-
result = self.getDistinctJobAttributes("Site")
|
|
1186
|
-
if not result["OK"]:
|
|
1187
|
-
return result
|
|
1188
|
-
|
|
1189
|
-
siteList = result["Value"]
|
|
1190
|
-
siteDict = {}
|
|
1191
|
-
totalDict = {
|
|
1192
|
-
JobStatus.WAITING: 0,
|
|
1193
|
-
JobStatus.RUNNING: 0,
|
|
1194
|
-
JobStatus.STALLED: 0,
|
|
1195
|
-
JobStatus.DONE: 0,
|
|
1196
|
-
JobStatus.FAILED: 0,
|
|
1197
|
-
}
|
|
1198
|
-
|
|
1199
|
-
for site in siteList:
|
|
1200
|
-
if site == "ANY":
|
|
1201
|
-
continue
|
|
1202
|
-
# Waiting
|
|
1203
|
-
siteDict[site] = {}
|
|
1204
|
-
ret = self._escapeString(site)
|
|
1205
|
-
if not ret["OK"]:
|
|
1206
|
-
return ret
|
|
1207
|
-
e_site = ret["Value"]
|
|
1208
|
-
|
|
1209
|
-
req = f"SELECT COUNT(JobID) FROM Jobs WHERE Status IN ({waitingString}) AND Site={e_site}"
|
|
1210
|
-
result = self._query(req)
|
|
1211
|
-
if result["OK"]:
|
|
1212
|
-
count = result["Value"][0][0]
|
|
1213
|
-
else:
|
|
1214
|
-
return S_ERROR("Failed to get Site data from the JobDB")
|
|
1215
|
-
siteDict[site][JobStatus.WAITING] = count
|
|
1216
|
-
totalDict[JobStatus.WAITING] += count
|
|
1217
|
-
# Running,Stalled,Done,Failed
|
|
1218
|
-
for status in [
|
|
1219
|
-
f'"{JobStatus.RUNNING}"',
|
|
1220
|
-
f'"{JobStatus.STALLED}"',
|
|
1221
|
-
f'"{JobStatus.DONE}"',
|
|
1222
|
-
f'"{JobStatus.FAILED}"',
|
|
1223
|
-
]:
|
|
1224
|
-
req = f"SELECT COUNT(JobID) FROM Jobs WHERE Status={status} AND Site={e_site}"
|
|
1225
|
-
result = self._query(req)
|
|
1226
|
-
if result["OK"]:
|
|
1227
|
-
count = result["Value"][0][0]
|
|
1228
|
-
else:
|
|
1229
|
-
return S_ERROR("Failed to get Site data from the JobDB")
|
|
1230
|
-
siteDict[site][status.replace('"', "")] = count
|
|
1231
|
-
totalDict[status.replace('"', "")] += count
|
|
1232
|
-
|
|
1233
|
-
siteDict["Total"] = totalDict
|
|
1234
|
-
return S_OK(siteDict)
|
|
1235
|
-
|
|
1236
1193
|
#################################################################################
|
|
1237
1194
|
def getSiteSummaryWeb(self, selectDict, sortList, startItem, maxItems):
|
|
1238
1195
|
"""Get the summary of jobs in a given status on all the sites in the standard Web form"""
|
|
@@ -28,7 +28,7 @@ CREATE TABLE `JobJDLs` (
|
|
|
28
28
|
`JobRequirements` TEXT NOT NULL,
|
|
29
29
|
`OriginalJDL` MEDIUMTEXT NOT NULL,
|
|
30
30
|
PRIMARY KEY (`JobID`)
|
|
31
|
-
) ENGINE=InnoDB DEFAULT CHARSET=
|
|
31
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
32
32
|
|
|
33
33
|
-- ------------------------------------------------------------------------------
|
|
34
34
|
DROP TABLE IF EXISTS `Jobs`;
|
|
@@ -66,7 +66,7 @@ CREATE TABLE `Jobs` (
|
|
|
66
66
|
KEY `ApplicationStatus` (`ApplicationStatus`),
|
|
67
67
|
KEY `StatusSite` (`Status`,`Site`),
|
|
68
68
|
KEY `LastUpdateTime` (`LastUpdateTime`)
|
|
69
|
-
) ENGINE=InnoDB DEFAULT CHARSET=
|
|
69
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
70
70
|
|
|
71
71
|
-- ------------------------------------------------------------------------------
|
|
72
72
|
DROP TABLE IF EXISTS `InputData`;
|
|
@@ -76,7 +76,7 @@ CREATE TABLE `InputData` (
|
|
|
76
76
|
`Status` VARCHAR(32) NOT NULL DEFAULT 'AprioriGood',
|
|
77
77
|
PRIMARY KEY (`JobID`,`LFN`),
|
|
78
78
|
FOREIGN KEY (`JobID`) REFERENCES `Jobs`(`JobID`)
|
|
79
|
-
) ENGINE=InnoDB DEFAULT CHARSET=
|
|
79
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
80
80
|
|
|
81
81
|
-- ------------------------------------------------------------------------------
|
|
82
82
|
DROP TABLE IF EXISTS `JobParameters`;
|
|
@@ -86,7 +86,7 @@ CREATE TABLE `JobParameters` (
|
|
|
86
86
|
`Value` TEXT NOT NULL,
|
|
87
87
|
PRIMARY KEY (`JobID`,`Name`),
|
|
88
88
|
FOREIGN KEY (`JobID`) REFERENCES `Jobs`(`JobID`)
|
|
89
|
-
) ENGINE=InnoDB DEFAULT CHARSET=
|
|
89
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
90
90
|
|
|
91
91
|
-- ------------------------------------------------------------------------------
|
|
92
92
|
DROP TABLE IF EXISTS `OptimizerParameters`;
|
|
@@ -96,7 +96,7 @@ CREATE TABLE `OptimizerParameters` (
|
|
|
96
96
|
`Value` MEDIUMTEXT NOT NULL,
|
|
97
97
|
PRIMARY KEY (`JobID`,`Name`),
|
|
98
98
|
FOREIGN KEY (`JobID`) REFERENCES `Jobs`(`JobID`)
|
|
99
|
-
) ENGINE=InnoDB DEFAULT CHARSET=
|
|
99
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
100
100
|
|
|
101
101
|
-- ------------------------------------------------------------------------------
|
|
102
102
|
DROP TABLE IF EXISTS `AtticJobParameters`;
|
|
@@ -107,7 +107,7 @@ CREATE TABLE `AtticJobParameters` (
|
|
|
107
107
|
`RescheduleCycle` INT(11) UNSIGNED NOT NULL,
|
|
108
108
|
PRIMARY KEY (`JobID`,`Name`,`RescheduleCycle`),
|
|
109
109
|
FOREIGN KEY (`JobID`) REFERENCES `Jobs`(`JobID`)
|
|
110
|
-
) ENGINE=InnoDB DEFAULT CHARSET=
|
|
110
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
111
111
|
|
|
112
112
|
-- ------------------------------------------------------------------------------
|
|
113
113
|
DROP TABLE IF EXISTS `HeartBeatLoggingInfo`;
|
|
@@ -118,7 +118,7 @@ CREATE TABLE `HeartBeatLoggingInfo` (
|
|
|
118
118
|
`HeartBeatTime` DATETIME NOT NULL,
|
|
119
119
|
PRIMARY KEY (`JobID`,`Name`,`HeartBeatTime`),
|
|
120
120
|
FOREIGN KEY (`JobID`) REFERENCES `Jobs`(`JobID`)
|
|
121
|
-
) ENGINE=InnoDB DEFAULT CHARSET=
|
|
121
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
122
122
|
|
|
123
123
|
-- ------------------------------------------------------------------------------
|
|
124
124
|
DROP TABLE IF EXISTS `JobCommands`;
|
|
@@ -131,4 +131,4 @@ CREATE TABLE `JobCommands` (
|
|
|
131
131
|
`ExecutionTime` DATETIME DEFAULT NULL,
|
|
132
132
|
PRIMARY KEY (`JobID`,`Arguments`,`ReceptionTime`),
|
|
133
133
|
FOREIGN KEY (`JobID`) REFERENCES `Jobs`(`JobID`)
|
|
134
|
-
) ENGINE=InnoDB DEFAULT CHARSET=
|
|
134
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
@@ -1,162 +1,33 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
import
|
|
3
|
+
# Import stateless functions from DIRACCommon for backward compatibility
|
|
4
|
+
from DIRACCommon.WorkloadManagementSystem.DB.JobDBUtils import *
|
|
5
5
|
|
|
6
6
|
from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations
|
|
7
|
-
from DIRAC.Core.Utilities.DErrno import EWMSSUBM
|
|
8
7
|
from DIRAC.Core.Utilities.ObjectLoader import ObjectLoader
|
|
9
|
-
from DIRAC.Core.Utilities.ReturnValues import
|
|
10
|
-
from DIRAC.WorkloadManagementSystem.Client import
|
|
11
|
-
from DIRAC.WorkloadManagementSystem.Client.JobState.JobManifest import JobManifest
|
|
8
|
+
from DIRAC.Core.Utilities.ReturnValues import returnValueOrRaise
|
|
9
|
+
from DIRAC.WorkloadManagementSystem.Client.JobState.JobManifest import makeJobManifestConfig
|
|
12
10
|
|
|
13
11
|
getDIRACPlatform = returnValueOrRaise(
|
|
14
12
|
ObjectLoader().loadObject("ConfigurationSystem.Client.Helpers.Resources", "getDIRACPlatform")
|
|
15
13
|
)
|
|
16
14
|
|
|
17
15
|
|
|
18
|
-
def
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
def checkAndPrepareJob(
|
|
17
|
+
jobID, classAdJob, classAdReq, owner, ownerGroup, jobAttrs, vo
|
|
18
|
+
): # pylint: disable=function-redefined
|
|
19
|
+
from DIRACCommon.WorkloadManagementSystem.DB.JobDBUtils import checkAndPrepareJob
|
|
21
20
|
|
|
21
|
+
config = {
|
|
22
|
+
"inputDataPolicyForVO": Operations(vo=vo).getValue("InputDataPolicy/InputDataModule"),
|
|
23
|
+
"softwareDistModuleForVO": Operations(vo=vo).getValue("SoftwareDistModule"),
|
|
24
|
+
"defaultCPUTimeForOwnerGroup": Operations(group=ownerGroup).getValue("JobDescription/DefaultCPUTime", 86400),
|
|
25
|
+
"getDIRACPlatform": getDIRACPlatform,
|
|
26
|
+
}
|
|
27
|
+
return checkAndPrepareJob(jobID, classAdJob, classAdReq, owner, ownerGroup, jobAttrs, vo, config=config)
|
|
22
28
|
|
|
23
|
-
def extractJDL(compressedJDL):
|
|
24
|
-
"""Return decompressed JDL string."""
|
|
25
|
-
# the starting bracket is guaranteeed by JobManager.submitJob
|
|
26
|
-
# we need the check to be backward compatible
|
|
27
|
-
if isinstance(compressedJDL, bytes):
|
|
28
|
-
if compressedJDL.startswith(b"["):
|
|
29
|
-
return compressedJDL.decode()
|
|
30
|
-
else:
|
|
31
|
-
if compressedJDL.startswith("["):
|
|
32
|
-
return compressedJDL
|
|
33
|
-
return zlib.decompress(base64.b64decode(compressedJDL)).decode()
|
|
34
29
|
|
|
30
|
+
def checkAndAddOwner(jdl: str, owner: str, ownerGroup: str): # pylint: disable=function-redefined
|
|
31
|
+
from DIRACCommon.WorkloadManagementSystem.DB.JobDBUtils import checkAndAddOwner
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
jobManifest = JobManifest()
|
|
38
|
-
res = jobManifest.load(jdl)
|
|
39
|
-
if not res["OK"]:
|
|
40
|
-
return res
|
|
41
|
-
|
|
42
|
-
jobManifest.setOptionsFromDict({"Owner": owner, "OwnerGroup": ownerGroup})
|
|
43
|
-
res = jobManifest.check()
|
|
44
|
-
if not res["OK"]:
|
|
45
|
-
return res
|
|
46
|
-
|
|
47
|
-
return S_OK(jobManifest)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def fixJDL(jdl: str) -> str:
|
|
51
|
-
# 1.- insert original JDL on DB and get new JobID
|
|
52
|
-
# Fix the possible lack of the brackets in the JDL
|
|
53
|
-
if jdl.strip()[0].find("[") != 0:
|
|
54
|
-
jdl = "[" + jdl + "]"
|
|
55
|
-
return jdl
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def checkAndPrepareJob(jobID, classAdJob, classAdReq, owner, ownerGroup, jobAttrs, vo):
|
|
59
|
-
error = ""
|
|
60
|
-
|
|
61
|
-
jdlOwner = classAdJob.getAttributeString("Owner")
|
|
62
|
-
jdlOwnerGroup = classAdJob.getAttributeString("OwnerGroup")
|
|
63
|
-
jdlVO = classAdJob.getAttributeString("VirtualOrganization")
|
|
64
|
-
|
|
65
|
-
# The below is commented out since this is always overwritten by the submitter IDs
|
|
66
|
-
# but the check allows to findout inconsistent client environments
|
|
67
|
-
if jdlOwner and jdlOwner != owner:
|
|
68
|
-
error = "Wrong Owner in JDL"
|
|
69
|
-
elif jdlOwnerGroup and jdlOwnerGroup != ownerGroup:
|
|
70
|
-
error = "Wrong Owner Group in JDL"
|
|
71
|
-
elif jdlVO and jdlVO != vo:
|
|
72
|
-
error = "Wrong Virtual Organization in JDL"
|
|
73
|
-
|
|
74
|
-
classAdJob.insertAttributeString("Owner", owner)
|
|
75
|
-
classAdJob.insertAttributeString("OwnerGroup", ownerGroup)
|
|
76
|
-
|
|
77
|
-
if vo:
|
|
78
|
-
classAdJob.insertAttributeString("VirtualOrganization", vo)
|
|
79
|
-
|
|
80
|
-
classAdReq.insertAttributeString("Owner", owner)
|
|
81
|
-
classAdReq.insertAttributeString("OwnerGroup", ownerGroup)
|
|
82
|
-
if vo:
|
|
83
|
-
classAdReq.insertAttributeString("VirtualOrganization", vo)
|
|
84
|
-
|
|
85
|
-
inputDataPolicy = Operations(vo=vo).getValue("InputDataPolicy/InputDataModule")
|
|
86
|
-
if inputDataPolicy and not classAdJob.lookupAttribute("InputDataModule"):
|
|
87
|
-
classAdJob.insertAttributeString("InputDataModule", inputDataPolicy)
|
|
88
|
-
|
|
89
|
-
softwareDistModule = Operations(vo=vo).getValue("SoftwareDistModule")
|
|
90
|
-
if softwareDistModule and not classAdJob.lookupAttribute("SoftwareDistModule"):
|
|
91
|
-
classAdJob.insertAttributeString("SoftwareDistModule", softwareDistModule)
|
|
92
|
-
|
|
93
|
-
# priority
|
|
94
|
-
priority = classAdJob.getAttributeInt("Priority")
|
|
95
|
-
if priority is None:
|
|
96
|
-
priority = 0
|
|
97
|
-
classAdReq.insertAttributeInt("UserPriority", priority)
|
|
98
|
-
|
|
99
|
-
# CPU time
|
|
100
|
-
cpuTime = classAdJob.getAttributeInt("CPUTime")
|
|
101
|
-
if cpuTime is None:
|
|
102
|
-
opsHelper = Operations(group=ownerGroup)
|
|
103
|
-
cpuTime = opsHelper.getValue("JobDescription/DefaultCPUTime", 86400)
|
|
104
|
-
classAdReq.insertAttributeInt("CPUTime", cpuTime)
|
|
105
|
-
|
|
106
|
-
# platform(s)
|
|
107
|
-
platformList = classAdJob.getListFromExpression("Platform")
|
|
108
|
-
if platformList:
|
|
109
|
-
result = getDIRACPlatform(platformList)
|
|
110
|
-
if not result["OK"]:
|
|
111
|
-
return result
|
|
112
|
-
if result["Value"]:
|
|
113
|
-
classAdReq.insertAttributeVectorString("Platforms", result["Value"])
|
|
114
|
-
else:
|
|
115
|
-
error = "OS compatibility info not found"
|
|
116
|
-
if error:
|
|
117
|
-
retVal = S_ERROR(EWMSSUBM, error)
|
|
118
|
-
retVal["JobId"] = jobID
|
|
119
|
-
retVal["Status"] = JobStatus.FAILED
|
|
120
|
-
retVal["MinorStatus"] = error
|
|
121
|
-
|
|
122
|
-
jobAttrs["Status"] = JobStatus.FAILED
|
|
123
|
-
|
|
124
|
-
jobAttrs["MinorStatus"] = error
|
|
125
|
-
return retVal
|
|
126
|
-
return S_OK()
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def createJDLWithInitialStatus(
|
|
130
|
-
classAdJob, classAdReq, jdl2DBParameters, jobAttrs, initialStatus, initialMinorStatus, *, modern=False
|
|
131
|
-
):
|
|
132
|
-
"""
|
|
133
|
-
:param modern: if True, store boolean instead of string for VerifiedFlag (used by diracx only)
|
|
134
|
-
"""
|
|
135
|
-
priority = classAdJob.getAttributeInt("Priority")
|
|
136
|
-
if priority is None:
|
|
137
|
-
priority = 0
|
|
138
|
-
jobAttrs["UserPriority"] = priority
|
|
139
|
-
|
|
140
|
-
for jdlName in jdl2DBParameters:
|
|
141
|
-
# Defaults are set by the DB.
|
|
142
|
-
jdlValue = classAdJob.getAttributeString(jdlName)
|
|
143
|
-
if jdlValue:
|
|
144
|
-
jobAttrs[jdlName] = jdlValue
|
|
145
|
-
|
|
146
|
-
jdlValue = classAdJob.getAttributeString("Site")
|
|
147
|
-
if jdlValue:
|
|
148
|
-
if jdlValue.find(",") != -1:
|
|
149
|
-
jobAttrs["Site"] = "Multiple"
|
|
150
|
-
else:
|
|
151
|
-
jobAttrs["Site"] = jdlValue
|
|
152
|
-
|
|
153
|
-
jobAttrs["VerifiedFlag"] = True if modern else "True"
|
|
154
|
-
|
|
155
|
-
jobAttrs["Status"] = initialStatus
|
|
156
|
-
|
|
157
|
-
jobAttrs["MinorStatus"] = initialMinorStatus
|
|
158
|
-
|
|
159
|
-
reqJDL = classAdReq.asJDL()
|
|
160
|
-
classAdJob.insertAttributeInt("JobRequirements", reqJDL)
|
|
161
|
-
|
|
162
|
-
return classAdJob.asJDL()
|
|
33
|
+
return checkAndAddOwner(jdl, owner, ownerGroup, job_manifest_config=makeJobManifestConfig(ownerGroup))
|
|
@@ -11,6 +11,7 @@ import datetime
|
|
|
11
11
|
from DIRAC import S_ERROR, S_OK
|
|
12
12
|
from DIRAC.Core.Base.DB import DB
|
|
13
13
|
from DIRAC.Core.Utilities import TimeUtilities
|
|
14
|
+
from DIRAC.Core.Utilities.ReturnValues import returnValueOrRaise, convertToReturnValue
|
|
14
15
|
from DIRAC.FrameworkSystem.Client.Logger import contextLogger
|
|
15
16
|
|
|
16
17
|
MAGIC_EPOC_NUMBER = 1270000000
|
|
@@ -145,21 +146,33 @@ class JobLoggingDB(DB):
|
|
|
145
146
|
return S_OK(return_value)
|
|
146
147
|
|
|
147
148
|
#############################################################################
|
|
149
|
+
@convertToReturnValue
|
|
148
150
|
def deleteJob(self, jobID):
|
|
149
151
|
"""Delete logging records for given jobs"""
|
|
150
152
|
if not jobID:
|
|
151
|
-
return
|
|
153
|
+
return None
|
|
152
154
|
|
|
153
|
-
# Make sure that we have a list of strings of jobIDs
|
|
154
155
|
if isinstance(jobID, int):
|
|
155
|
-
jobList = [
|
|
156
|
+
jobList = [jobID]
|
|
156
157
|
elif isinstance(jobID, str):
|
|
157
158
|
jobList = jobID.replace(" ", "").split(",")
|
|
158
159
|
else:
|
|
159
|
-
jobList =
|
|
160
|
+
jobList = jobID
|
|
160
161
|
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
sqlCmd = (
|
|
163
|
+
"CREATE TEMPORARY TABLE to_delete_LoggingInfo (JobID INTEGER NOT NULL, PRIMARY KEY (JobID)) ENGINE=MEMORY;"
|
|
164
|
+
)
|
|
165
|
+
returnValueOrRaise(self._update(sqlCmd))
|
|
166
|
+
try:
|
|
167
|
+
sqlCmd = "INSERT INTO to_delete_LoggingInfo (JobID) VALUES ( %s )"
|
|
168
|
+
returnValueOrRaise(self._updatemany(sqlCmd, [(j,) for j in jobList]))
|
|
169
|
+
sqlCmd = "DELETE l from `LoggingInfo` l JOIN to_delete_LoggingInfo t USING (JobID)"
|
|
170
|
+
result = returnValueOrRaise(self._update(sqlCmd))
|
|
171
|
+
finally:
|
|
172
|
+
sqlCmd = "DROP TEMPORARY TABLE to_delete_LoggingInfo"
|
|
173
|
+
returnValueOrRaise(self._update(sqlCmd))
|
|
174
|
+
|
|
175
|
+
return result
|
|
163
176
|
|
|
164
177
|
#############################################################################
|
|
165
178
|
def getWMSTimeStamps(self, jobID):
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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/
|
|
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
|
|
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")
|
|
@@ -69,7 +69,7 @@ class JobParametersDB(ElasticDB):
|
|
|
69
69
|
raise RuntimeError(result["Message"])
|
|
70
70
|
self.log.always("Index created:", indexName)
|
|
71
71
|
|
|
72
|
-
def getJobParameters(self, jobIDs: int | list[int], vo: str, paramList=None) -> dict:
|
|
72
|
+
def getJobParameters(self, jobIDs: int | list[int], vo: str, paramList: list[str] | None = None) -> dict:
|
|
73
73
|
"""Get Job Parameters defined for jobID.
|
|
74
74
|
Returns a dictionary with the Job Parameters.
|
|
75
75
|
If paramList is empty - all the parameters are returned.
|