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.
Files changed (236) 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 +38 -26
  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 +32 -19
  14. DIRAC/ConfigurationSystem/Client/test/Test_PathFinder.py +41 -1
  15. DIRAC/ConfigurationSystem/private/RefresherBase.py +4 -2
  16. DIRAC/Core/Base/API.py +4 -7
  17. DIRAC/Core/Base/SQLAlchemyDB.py +1 -0
  18. DIRAC/Core/DISET/ServiceReactor.py +11 -3
  19. DIRAC/Core/DISET/private/BaseClient.py +1 -2
  20. DIRAC/Core/DISET/private/Transports/M2SSLTransport.py +9 -7
  21. DIRAC/Core/DISET/private/Transports/SSL/M2Utils.py +3 -1
  22. DIRAC/Core/LCG/GOCDBClient.py +5 -7
  23. DIRAC/Core/Security/DiracX.py +31 -17
  24. DIRAC/Core/Security/IAMService.py +5 -10
  25. DIRAC/Core/Security/Locations.py +27 -18
  26. DIRAC/Core/Security/ProxyInfo.py +9 -5
  27. DIRAC/Core/Security/VOMSService.py +2 -4
  28. DIRAC/Core/Security/m2crypto/X509Certificate.py +4 -6
  29. DIRAC/Core/Security/m2crypto/asn1_utils.py +17 -5
  30. DIRAC/Core/Security/test/test_diracx_token_from_pem.py +161 -0
  31. DIRAC/Core/Tornado/Client/ClientSelector.py +4 -1
  32. DIRAC/Core/Tornado/Server/TornadoService.py +1 -1
  33. DIRAC/Core/Utilities/CGroups2.py +328 -0
  34. DIRAC/Core/Utilities/ClassAd/ClassAdLight.py +4 -290
  35. DIRAC/Core/Utilities/DErrno.py +5 -309
  36. DIRAC/Core/Utilities/Extensions.py +10 -1
  37. DIRAC/Core/Utilities/File.py +1 -1
  38. DIRAC/Core/Utilities/Graphs/GraphData.py +1 -1
  39. DIRAC/Core/Utilities/Graphs/GraphUtilities.py +6 -1
  40. DIRAC/Core/Utilities/JDL.py +1 -195
  41. DIRAC/Core/Utilities/List.py +1 -124
  42. DIRAC/Core/Utilities/MySQL.py +103 -99
  43. DIRAC/Core/Utilities/Os.py +32 -1
  44. DIRAC/Core/Utilities/Platform.py +2 -107
  45. DIRAC/Core/Utilities/Proxy.py +0 -4
  46. DIRAC/Core/Utilities/ReturnValues.py +7 -252
  47. DIRAC/Core/Utilities/StateMachine.py +12 -178
  48. DIRAC/Core/Utilities/Subprocess.py +35 -14
  49. DIRAC/Core/Utilities/TimeUtilities.py +10 -253
  50. DIRAC/Core/Utilities/test/Test_JDL.py +0 -3
  51. DIRAC/Core/Utilities/test/Test_Profiler.py +20 -20
  52. DIRAC/Core/scripts/dirac_agent.py +1 -1
  53. DIRAC/Core/scripts/dirac_apptainer_exec.py +72 -46
  54. DIRAC/Core/scripts/dirac_configure.py +1 -3
  55. DIRAC/Core/scripts/dirac_install_db.py +24 -6
  56. DIRAC/Core/scripts/dirac_platform.py +1 -92
  57. DIRAC/DataManagementSystem/Agent/FTS3Agent.py +8 -7
  58. DIRAC/DataManagementSystem/Agent/RequestOperations/RemoveFile.py +7 -6
  59. DIRAC/DataManagementSystem/Client/FTS3Job.py +71 -34
  60. DIRAC/DataManagementSystem/DB/FTS3DB.py +7 -3
  61. DIRAC/DataManagementSystem/DB/FileCatalogComponents/DatasetManager/DatasetManager.py +1 -1
  62. DIRAC/DataManagementSystem/DB/FileCatalogDB.sql +9 -9
  63. DIRAC/DataManagementSystem/DB/FileCatalogWithFkAndPsDB.sql +9 -9
  64. DIRAC/DataManagementSystem/Utilities/DMSHelpers.py +6 -2
  65. DIRAC/DataManagementSystem/scripts/dirac_admin_allow_se.py +13 -8
  66. DIRAC/DataManagementSystem/scripts/dirac_admin_ban_se.py +13 -8
  67. DIRAC/DataManagementSystem/scripts/dirac_dms_create_moving_request.py +2 -0
  68. DIRAC/DataManagementSystem/scripts/dirac_dms_protocol_matrix.py +0 -1
  69. DIRAC/FrameworkSystem/Client/BundleDeliveryClient.py +2 -7
  70. DIRAC/FrameworkSystem/Client/ComponentInstaller.py +9 -4
  71. DIRAC/FrameworkSystem/Client/ProxyManagerClient.py +5 -2
  72. DIRAC/FrameworkSystem/Client/SystemAdministratorClientCLI.py +11 -6
  73. DIRAC/FrameworkSystem/ConfigTemplate.cfg +2 -0
  74. DIRAC/FrameworkSystem/DB/AuthDB.py +3 -3
  75. DIRAC/FrameworkSystem/DB/InstalledComponentsDB.py +4 -4
  76. DIRAC/FrameworkSystem/DB/ProxyDB.py +11 -3
  77. DIRAC/FrameworkSystem/DB/TokenDB.py +1 -1
  78. DIRAC/FrameworkSystem/Service/ProxyManagerHandler.py +8 -6
  79. DIRAC/FrameworkSystem/Utilities/MonitoringUtilities.py +2 -19
  80. DIRAC/FrameworkSystem/Utilities/TokenManagementUtilities.py +3 -2
  81. DIRAC/FrameworkSystem/Utilities/diracx.py +36 -14
  82. DIRAC/FrameworkSystem/private/authorization/AuthServer.py +2 -2
  83. DIRAC/FrameworkSystem/scripts/dirac_admin_update_pilot.py +18 -11
  84. DIRAC/FrameworkSystem/scripts/dirac_login.py +2 -2
  85. DIRAC/FrameworkSystem/scripts/dirac_proxy_init.py +7 -8
  86. DIRAC/Interfaces/API/Dirac.py +27 -15
  87. DIRAC/Interfaces/API/DiracAdmin.py +45 -17
  88. DIRAC/Interfaces/API/Job.py +9 -13
  89. DIRAC/Interfaces/scripts/dirac_admin_allow_site.py +12 -18
  90. DIRAC/Interfaces/scripts/dirac_admin_ban_site.py +12 -10
  91. DIRAC/Interfaces/scripts/dirac_admin_get_site_mask.py +4 -13
  92. DIRAC/Interfaces/scripts/dirac_admin_reset_job.py +3 -6
  93. DIRAC/Interfaces/scripts/dirac_wms_job_parameters.py +0 -1
  94. DIRAC/MonitoringSystem/Client/Types/WMSHistory.py +4 -0
  95. DIRAC/MonitoringSystem/Client/WebAppClient.py +26 -0
  96. DIRAC/MonitoringSystem/ConfigTemplate.cfg +9 -0
  97. DIRAC/MonitoringSystem/DB/MonitoringDB.py +6 -25
  98. DIRAC/MonitoringSystem/Service/MonitoringHandler.py +0 -33
  99. DIRAC/MonitoringSystem/Service/WebAppHandler.py +599 -0
  100. DIRAC/MonitoringSystem/private/MainReporter.py +0 -3
  101. DIRAC/ProductionSystem/DB/ProductionDB.sql +4 -4
  102. DIRAC/ProductionSystem/scripts/dirac_prod_get.py +2 -2
  103. DIRAC/ProductionSystem/scripts/dirac_prod_get_all.py +2 -2
  104. DIRAC/ProductionSystem/scripts/dirac_prod_get_trans.py +2 -3
  105. DIRAC/RequestManagementSystem/Agent/RequestExecutingAgent.py +8 -6
  106. DIRAC/RequestManagementSystem/Agent/RequestOperations/ForwardDISET.py +2 -14
  107. DIRAC/RequestManagementSystem/Client/ReqClient.py +66 -13
  108. DIRAC/RequestManagementSystem/ConfigTemplate.cfg +6 -6
  109. DIRAC/RequestManagementSystem/DB/RequestDB.py +10 -5
  110. DIRAC/RequestManagementSystem/DB/test/RMSTestScenari.py +2 -0
  111. DIRAC/RequestManagementSystem/private/RequestValidator.py +40 -46
  112. DIRAC/ResourceStatusSystem/Client/SiteStatus.py +4 -2
  113. DIRAC/ResourceStatusSystem/Command/FreeDiskSpaceCommand.py +3 -1
  114. DIRAC/ResourceStatusSystem/DB/ResourceManagementDB.py +8 -8
  115. DIRAC/ResourceStatusSystem/DB/ResourceStatusDB.py +2 -2
  116. DIRAC/ResourceStatusSystem/Utilities/CSHelpers.py +2 -31
  117. DIRAC/ResourceStatusSystem/scripts/dirac_rss_set_status.py +30 -12
  118. DIRAC/Resources/Catalog/RucioFileCatalogClient.py +195 -1
  119. DIRAC/Resources/Catalog/test/Test_RucioFileCatalogClient.py +181 -0
  120. DIRAC/Resources/Computing/AREXComputingElement.py +25 -8
  121. DIRAC/Resources/Computing/BatchSystems/Condor.py +126 -108
  122. DIRAC/Resources/Computing/BatchSystems/SLURM.py +5 -1
  123. DIRAC/Resources/Computing/BatchSystems/test/Test_SLURM.py +46 -0
  124. DIRAC/Resources/Computing/ComputingElement.py +1 -1
  125. DIRAC/Resources/Computing/HTCondorCEComputingElement.py +44 -44
  126. DIRAC/Resources/Computing/InProcessComputingElement.py +4 -2
  127. DIRAC/Resources/Computing/LocalComputingElement.py +1 -18
  128. DIRAC/Resources/Computing/SSHBatchComputingElement.py +1 -17
  129. DIRAC/Resources/Computing/SSHComputingElement.py +1 -18
  130. DIRAC/Resources/Computing/SingularityComputingElement.py +19 -5
  131. DIRAC/Resources/Computing/test/Test_HTCondorCEComputingElement.py +67 -49
  132. DIRAC/Resources/Computing/test/Test_PoolComputingElement.py +2 -1
  133. DIRAC/Resources/IdProvider/CheckInIdProvider.py +13 -0
  134. DIRAC/Resources/IdProvider/IdProviderFactory.py +11 -3
  135. DIRAC/Resources/MessageQueue/StompMQConnector.py +1 -1
  136. DIRAC/Resources/Storage/GFAL2_StorageBase.py +24 -15
  137. DIRAC/Resources/Storage/OccupancyPlugins/WLCGAccountingHTTPJson.py +1 -3
  138. DIRAC/Resources/Storage/StorageBase.py +4 -2
  139. DIRAC/Resources/Storage/StorageElement.py +6 -7
  140. DIRAC/StorageManagementSystem/DB/StorageManagementDB.sql +2 -2
  141. DIRAC/TransformationSystem/Agent/TaskManagerAgentBase.py +10 -16
  142. DIRAC/TransformationSystem/Agent/TransformationAgent.py +22 -1
  143. DIRAC/TransformationSystem/Agent/TransformationCleaningAgent.py +16 -16
  144. DIRAC/TransformationSystem/Client/TaskManager.py +2 -4
  145. DIRAC/TransformationSystem/Client/Transformation.py +6 -7
  146. DIRAC/TransformationSystem/Client/TransformationClient.py +21 -11
  147. DIRAC/TransformationSystem/Client/Utilities.py +9 -0
  148. DIRAC/TransformationSystem/DB/TransformationDB.py +11 -14
  149. DIRAC/TransformationSystem/DB/TransformationDB.sql +9 -9
  150. DIRAC/TransformationSystem/Service/TransformationManagerHandler.py +0 -333
  151. DIRAC/TransformationSystem/Utilities/ReplicationCLIParameters.py +3 -3
  152. DIRAC/TransformationSystem/Utilities/TransformationInfo.py +7 -5
  153. DIRAC/TransformationSystem/scripts/dirac_production_runjoblocal.py +2 -4
  154. DIRAC/TransformationSystem/test/Test_TransformationInfo.py +22 -15
  155. DIRAC/TransformationSystem/test/Test_replicationTransformation.py +5 -6
  156. DIRAC/Workflow/Modules/test/Test_Modules.py +5 -0
  157. DIRAC/WorkloadManagementSystem/Agent/JobAgent.py +38 -26
  158. DIRAC/WorkloadManagementSystem/Agent/JobCleaningAgent.py +12 -8
  159. DIRAC/WorkloadManagementSystem/Agent/PilotSyncAgent.py +4 -3
  160. DIRAC/WorkloadManagementSystem/Agent/PushJobAgent.py +13 -13
  161. DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py +18 -14
  162. DIRAC/WorkloadManagementSystem/Agent/StalledJobAgent.py +18 -51
  163. DIRAC/WorkloadManagementSystem/Agent/StatesAccountingAgent.py +41 -1
  164. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobAgent.py +45 -4
  165. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobCleaningAgent.py +7 -9
  166. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PushJobAgent.py +1 -0
  167. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_SiteDirector.py +9 -2
  168. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_StalledJobAgent.py +4 -5
  169. DIRAC/WorkloadManagementSystem/Client/DownloadInputData.py +9 -9
  170. DIRAC/WorkloadManagementSystem/Client/InputDataResolution.py +6 -6
  171. DIRAC/WorkloadManagementSystem/Client/JobMonitoringClient.py +10 -11
  172. DIRAC/WorkloadManagementSystem/Client/JobReport.py +1 -1
  173. DIRAC/WorkloadManagementSystem/Client/JobState/CachedJobState.py +3 -0
  174. DIRAC/WorkloadManagementSystem/Client/JobState/JobManifest.py +32 -261
  175. DIRAC/WorkloadManagementSystem/Client/JobState/JobState.py +6 -0
  176. DIRAC/WorkloadManagementSystem/Client/JobStateUpdateClient.py +3 -0
  177. DIRAC/WorkloadManagementSystem/Client/JobStatus.py +8 -152
  178. DIRAC/WorkloadManagementSystem/Client/PoolXMLSlice.py +12 -19
  179. DIRAC/WorkloadManagementSystem/Client/SandboxStoreClient.py +25 -38
  180. DIRAC/WorkloadManagementSystem/Client/WMSClient.py +2 -3
  181. DIRAC/WorkloadManagementSystem/Client/test/Test_Client_DownloadInputData.py +29 -0
  182. DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg +4 -8
  183. DIRAC/WorkloadManagementSystem/DB/JobDB.py +89 -132
  184. DIRAC/WorkloadManagementSystem/DB/JobDB.sql +8 -8
  185. DIRAC/WorkloadManagementSystem/DB/JobDBUtils.py +18 -147
  186. DIRAC/WorkloadManagementSystem/DB/JobLoggingDB.py +19 -6
  187. DIRAC/WorkloadManagementSystem/DB/JobParametersDB.py +9 -9
  188. DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py +16 -5
  189. DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.sql +3 -3
  190. DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py +44 -82
  191. DIRAC/WorkloadManagementSystem/DB/StatusUtils.py +125 -0
  192. DIRAC/WorkloadManagementSystem/DB/tests/Test_JobDB.py +1 -1
  193. DIRAC/WorkloadManagementSystem/DB/tests/Test_StatusUtils.py +28 -0
  194. DIRAC/WorkloadManagementSystem/Executor/JobSanity.py +5 -4
  195. DIRAC/WorkloadManagementSystem/Executor/JobScheduling.py +4 -0
  196. DIRAC/WorkloadManagementSystem/FutureClient/JobStateUpdateClient.py +75 -33
  197. DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapper.py +22 -11
  198. DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapperTemplate.py +9 -10
  199. DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapper.py +60 -10
  200. DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapperTemplate.py +4 -0
  201. DIRAC/WorkloadManagementSystem/Service/JobManagerHandler.py +33 -154
  202. DIRAC/WorkloadManagementSystem/Service/JobMonitoringHandler.py +5 -323
  203. DIRAC/WorkloadManagementSystem/Service/JobStateUpdateHandler.py +0 -16
  204. DIRAC/WorkloadManagementSystem/Service/PilotManagerHandler.py +6 -103
  205. DIRAC/WorkloadManagementSystem/Service/SandboxStoreHandler.py +7 -53
  206. DIRAC/WorkloadManagementSystem/Service/WMSAdministratorHandler.py +16 -79
  207. DIRAC/WorkloadManagementSystem/Service/WMSUtilities.py +4 -18
  208. DIRAC/WorkloadManagementSystem/Utilities/JobModel.py +28 -209
  209. DIRAC/WorkloadManagementSystem/Utilities/JobParameters.py +65 -3
  210. DIRAC/WorkloadManagementSystem/Utilities/JobStatusUtility.py +2 -64
  211. DIRAC/WorkloadManagementSystem/Utilities/ParametricJob.py +7 -171
  212. DIRAC/WorkloadManagementSystem/Utilities/PilotCStoJSONSynchronizer.py +73 -7
  213. DIRAC/WorkloadManagementSystem/Utilities/PilotWrapper.py +41 -11
  214. DIRAC/WorkloadManagementSystem/Utilities/RemoteRunner.py +16 -0
  215. DIRAC/WorkloadManagementSystem/Utilities/Utils.py +36 -1
  216. DIRAC/WorkloadManagementSystem/Utilities/jobAdministration.py +15 -0
  217. DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobModel.py +1 -15
  218. DIRAC/WorkloadManagementSystem/Utilities/test/Test_ParametricJob.py +45 -128
  219. DIRAC/WorkloadManagementSystem/Utilities/test/Test_PilotWrapper.py +16 -0
  220. DIRAC/WorkloadManagementSystem/scripts/dirac_jobexec.py +7 -2
  221. DIRAC/WorkloadManagementSystem/scripts/dirac_wms_pilot_job_info.py +1 -1
  222. DIRAC/__init__.py +62 -60
  223. DIRAC/tests/Utilities/testJobDefinitions.py +22 -28
  224. {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/METADATA +8 -5
  225. {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/RECORD +229 -228
  226. {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/WHEEL +1 -1
  227. {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/entry_points.txt +0 -3
  228. DIRAC/Core/Utilities/test/Test_List.py +0 -150
  229. DIRAC/Core/Utilities/test/Test_Time.py +0 -88
  230. DIRAC/Resources/Computing/PilotBundle.py +0 -70
  231. DIRAC/TransformationSystem/scripts/dirac_transformation_archive.py +0 -30
  232. DIRAC/TransformationSystem/scripts/dirac_transformation_clean.py +0 -30
  233. DIRAC/TransformationSystem/scripts/dirac_transformation_remove_output.py +0 -30
  234. DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobManager.py +0 -58
  235. {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info/licenses}/LICENSE +0 -0
  236. {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 S_ERROR, S_OK
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 S_OK({})
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
- ret = self._escapeString(x)
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
- cmd = f"SELECT {attrNames} FROM Jobs WHERE JobID IN ({','.join(str(jobID) for jobID in jobIDs)})"
240
- res = self._query(cmd)
241
- if not res["OK"]:
242
- return res
243
- if not res["Value"]:
244
- return S_OK({})
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 res["Value"]:
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 S_OK(attributes)
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
- def getInputData(self, jobID):
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
- ret = self._escapeString(jobID)
336
- if not ret["OK"]:
337
- return ret
338
- jobID = ret["Value"]
339
- cmd = f"SELECT LFN FROM InputData WHERE JobID={jobID}"
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
- inputData = [i[0] for i in res["Value"] if i[0].strip()]
345
- for index, lfn in enumerate(inputData):
359
+ for jid, lfn in res["Value"]:
360
+ lfn = lfn.strip()
346
361
  if lfn.lower().startswith("lfn:"):
347
- inputData[index] = lfn[4:]
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(inputData)
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
- jIDList = []
531
- for jID in jobIDList:
532
- ret = self._escapeString(jID)
533
- if not ret["OK"]:
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 S_OK()
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
- if failedTablesList:
1025
- return S_ERROR(f"Errors while job removal (tables {','.join(failedTablesList)})")
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
- return S_OK()
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=latin1;
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=latin1;
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=latin1;
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=latin1;
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=latin1;
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=latin1;
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=latin1;
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=latin1;
134
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -1,162 +1,33 @@
1
1
  from __future__ import annotations
2
2
 
3
- import base64
4
- import zlib
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 S_ERROR, S_OK, returnValueOrRaise
10
- from DIRAC.WorkloadManagementSystem.Client import JobStatus
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 compressJDL(jdl):
19
- """Return compressed JDL string."""
20
- return base64.b64encode(zlib.compress(jdl.encode(), -1)).decode()
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
- def checkAndAddOwner(jdl: str, owner: str, ownerGroup: str) -> JobManifest:
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 S_OK()
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 = [str(jobID)]
156
+ jobList = [jobID]
156
157
  elif isinstance(jobID, str):
157
158
  jobList = jobID.replace(" ", "").split(",")
158
159
  else:
159
- jobList = list(str(j) for j in jobID)
160
+ jobList = jobID
160
161
 
161
- req = f"DELETE FROM LoggingInfo WHERE JobID IN ({','.join(jobList)})"
162
- return self._update(req)
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
- """ Module containing a front-end to the OpenSearch-based JobParametersDB.
2
- This is a drop-in replacement for MySQL-based table JobDB.JobParameters.
1
+ """Module containing a front-end to the OpenSearch-based JobParametersDB.
2
+ This is a drop-in replacement for MySQL-based table JobDB.JobParameters.
3
3
 
4
- The following class methods are provided for public usage
5
- - getJobParameters()
6
- - setJobParameter()
7
- - deleteJobParameters()
4
+ The following class methods are provided for public usage
5
+ - getJobParameters()
6
+ - setJobParameter()
7
+ - deleteJobParameters()
8
8
  """
9
9
 
10
10
  from DIRAC import S_ERROR, S_OK
@@ -37,11 +37,11 @@ class JobParametersDB(ElasticDB):
37
37
  def __init__(self, parentLogger=None):
38
38
  """Standard Constructor"""
39
39
 
40
- self.fullname = "WorkloadManagement/ElasticJobParametersDB"
40
+ self.fullname = "WorkloadManagement/JobParametersDB"
41
41
  self.index_name = self.getCSOption("index_name", "job_parameters")
42
42
 
43
43
  try:
44
- # Connecting to the ES cluster
44
+ # Connecting to the OpenSearch cluster
45
45
  super().__init__(self.fullname, self.index_name, parentLogger=parentLogger)
46
46
  except Exception:
47
47
  RuntimeError("Can't connect to JobParameters index")
@@ -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.