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,6 +11,7 @@ from DIRAC.WorkloadManagementSystem.Service.JobPolicy import (
11
11
  RIGHT_GET_INFO,
12
12
  RIGHT_RESCHEDULE,
13
13
  RIGHT_RESET,
14
+ RIGHT_SUBMIT,
14
15
  )
15
16
  from DIRAC.WorkloadManagementSystem.Utilities.JobStatusUtility import JobStatusUtility
16
17
 
@@ -317,6 +318,11 @@ class JobState:
317
318
  def getInputData(self):
318
319
  return JobState.__db.jobDB.getInputData(self.__jid)
319
320
 
321
+ right_setInputData = RIGHT_SUBMIT
322
+
323
+ def setInputData(self, inputData):
324
+ return JobState.__db.jobDB.setInputData(self.__jid, inputData)
325
+
320
326
  right_insertIntoTQ = RIGHT_CHANGE_STATUS
321
327
 
322
328
  def insertIntoTQ(self, manifest=None):
@@ -28,3 +28,6 @@ class JobStateUpdateClient(Client):
28
28
 
29
29
  else:
30
30
  self.serverURL = url
31
+
32
+ def setJobStatus(self, jobID, status="", minorStatus="", source="Unknown", datetime_=None, force=False, **kwargs):
33
+ return self._getRPC(**kwargs).setJobStatus(jobID, status, minorStatus, source, datetime_, force)
@@ -1,154 +1,10 @@
1
- """
2
- This module contains constants and lists for the possible job states.
3
- """
4
-
5
- from DIRAC import gLogger, S_OK, S_ERROR
6
- from DIRAC.Core.Utilities.StateMachine import State, StateMachine
7
- from DIRAC.Core.Utilities.Decorators import deprecated
8
-
9
- from DIRAC.WorkloadManagementSystem.Client.JobMonitoringClient import JobMonitoringClient
10
-
11
-
12
- #:
13
- SUBMITTING = "Submitting"
14
- #:
15
- RECEIVED = "Received"
16
- #:
17
- CHECKING = "Checking"
18
- #:
19
- STAGING = "Staging"
20
- #:
21
- SCOUTING = "Scouting"
22
- #:
23
- WAITING = "Waiting"
24
- #:
25
- MATCHED = "Matched"
26
- #: The Rescheduled status is effectively never stored in the DB.
27
- #: It could be considered a "virtual" status, and might even be dropped.
28
- RESCHEDULED = "Rescheduled"
29
- #:
30
- RUNNING = "Running"
31
- #:
32
- STALLED = "Stalled"
33
- #:
34
- COMPLETING = "Completing"
35
- #:
36
- DONE = "Done"
37
- #:
38
- COMPLETED = "Completed"
39
- #:
40
- FAILED = "Failed"
41
- #:
42
- DELETED = "Deleted"
43
- #:
44
- KILLED = "Killed"
45
-
46
- #: Possible job states
47
- JOB_STATES = [
48
- SUBMITTING,
49
- RECEIVED,
50
- CHECKING,
51
- SCOUTING,
52
- STAGING,
53
- WAITING,
54
- MATCHED,
55
- RESCHEDULED,
56
- RUNNING,
57
- STALLED,
58
- COMPLETING,
59
- DONE,
60
- COMPLETED,
61
- FAILED,
62
- DELETED,
63
- KILLED,
64
- ]
65
-
66
- # Job States when the payload work has finished
67
- JOB_FINAL_STATES = [DONE, COMPLETED, FAILED, KILLED]
68
-
69
- # WMS internal job States indicating the job object won't be updated
70
- JOB_REALLY_FINAL_STATES = [DELETED]
71
-
72
-
73
- class JobsStateMachine(StateMachine):
74
- """Jobs state machine"""
75
-
76
- def __init__(self, state):
77
- """c'tor
78
- Defines the state machine transactions
79
- """
80
- super().__init__(state)
1
+ """Backward compatibility wrapper - moved to DIRACCommon
81
2
 
82
- # States transitions
83
- self.states = {
84
- DELETED: State(15), # final state
85
- KILLED: State(14, [DELETED], defState=KILLED),
86
- FAILED: State(13, [RESCHEDULED, DELETED], defState=FAILED),
87
- DONE: State(12, [DELETED], defState=DONE),
88
- COMPLETED: State(11, [DONE, FAILED], defState=COMPLETED),
89
- COMPLETING: State(10, [DONE, FAILED, COMPLETED, STALLED, KILLED], defState=COMPLETING),
90
- STALLED: State(9, [RUNNING, FAILED, KILLED], defState=STALLED),
91
- RUNNING: State(8, [STALLED, DONE, FAILED, RESCHEDULED, COMPLETING, KILLED, RECEIVED], defState=RUNNING),
92
- RESCHEDULED: State(7, [WAITING, RECEIVED, DELETED, FAILED, KILLED], defState=RESCHEDULED),
93
- MATCHED: State(6, [RUNNING, FAILED, RESCHEDULED, KILLED], defState=MATCHED),
94
- WAITING: State(5, [MATCHED, RESCHEDULED, DELETED, KILLED], defState=WAITING),
95
- STAGING: State(4, [CHECKING, WAITING, FAILED, KILLED], defState=STAGING),
96
- SCOUTING: State(3, [CHECKING, FAILED, STALLED, KILLED], defState=SCOUTING),
97
- CHECKING: State(2, [SCOUTING, STAGING, WAITING, RESCHEDULED, FAILED, DELETED, KILLED], defState=CHECKING),
98
- RECEIVED: State(1, [SCOUTING, CHECKING, WAITING, FAILED, DELETED, KILLED], defState=RECEIVED),
99
- SUBMITTING: State(0, [RECEIVED, CHECKING, DELETED, KILLED], defState=SUBMITTING), # initial state
100
- }
3
+ This module has been moved to DIRACCommon.WorkloadManagementSystem.Client.JobStatus to avoid
4
+ circular dependencies and allow DiracX to use these utilities without
5
+ triggering DIRAC's global state initialization.
101
6
 
102
-
103
- @deprecated("Use filterJobStateTransition instead")
104
- def checkJobStateTransition(jobID, candidateState, currentStatus=None, jobMonitoringClient=None):
105
- """Utility to check if a job state transition is allowed"""
106
- if not currentStatus:
107
- if not jobMonitoringClient:
108
- from DIRAC.WorkloadManagementSystem.Client.JobMonitoringClient import JobMonitoringClient
109
-
110
- jobMonitoringClient = JobMonitoringClient()
111
-
112
- res = jobMonitoringClient.getJobsStatus(jobID)
113
- if not res["OK"]:
114
- return res
115
- try:
116
- currentStatus = res["Value"][jobID]["Status"]
117
- except KeyError:
118
- return S_ERROR("Job does not exist")
119
-
120
- res = JobsStateMachine(currentStatus).getNextState(candidateState)
121
- if not res["OK"]:
122
- return res
123
-
124
- # If the JobsStateMachine does not accept the candidate, return an ERROR
125
- if candidateState != res["Value"]:
126
- gLogger.error(
127
- "Job Status Error",
128
- f"{jobID} can't move from {currentStatus} to {candidateState}",
129
- )
130
- return S_ERROR("Job state transition not allowed")
131
- return S_OK()
132
-
133
-
134
- def filterJobStateTransition(jobIDs, candidateState):
135
- """Given a list of jobIDs, return a list that are allowed to transition
136
- to the given candidate state.
137
- """
138
- allowedJobs = []
139
-
140
- if not isinstance(jobIDs, list):
141
- jobIDs = [jobIDs]
142
-
143
- res = JobMonitoringClient().getJobsStatus(jobIDs)
144
- if not res["OK"]:
145
- return res
146
-
147
- for jobID in jobIDs:
148
- if jobID in res["Value"]:
149
- curState = res["Value"][jobID]["Status"]
150
- stateRes = JobsStateMachine(curState).getNextState(candidateState)
151
- if stateRes["OK"]:
152
- if stateRes["Value"] == candidateState:
153
- allowedJobs.append(jobID)
154
- return S_OK(allowedJobs)
7
+ All exports are maintained for backward compatibility.
8
+ """
9
+ # Re-export everything from DIRACCommon for backward compatibility
10
+ from DIRACCommon.WorkloadManagementSystem.Client.JobStatus import * # noqa: F401, F403
@@ -5,24 +5,19 @@
5
5
  """
6
6
  import os
7
7
 
8
- from DIRAC import S_OK, S_ERROR, gLogger
8
+ from DIRAC import S_ERROR, S_OK, gLogger
9
9
  from DIRAC.Resources.Catalog.PoolXMLCatalog import PoolXMLCatalog
10
10
 
11
- COMPONENT_NAME = "PoolXMLSlice"
12
-
13
11
 
14
12
  class PoolXMLSlice:
15
- #############################################################################
16
- def __init__(self, catalogName):
13
+ def __init__(self, catalogName, jobID_path: os.PathLike):
17
14
  """Standard constructor"""
18
15
  self.fileName = catalogName
19
- self.name = COMPONENT_NAME
20
- self.log = gLogger.getSubLogger(self.name)
16
+ self.jobID_path = jobID_path
17
+ self.log = gLogger.getSubLogger(self.__class__.__name__)
21
18
 
22
- #############################################################################
23
19
  def execute(self, dataDict):
24
20
  """Given a dictionary of resolved input data, this will creates a POOL XML slice."""
25
- poolXMLCatName = self.fileName
26
21
  try:
27
22
  poolXMLCat = PoolXMLCatalog()
28
23
  self.log.verbose("Creating POOL XML slice")
@@ -46,21 +41,19 @@ class PoolXMLSlice:
46
41
  xmlSlice = poolXMLCat.toXML()
47
42
  self.log.verbose("POOL XML Slice is: ")
48
43
  self.log.verbose(xmlSlice)
49
- with open(poolXMLCatName, "w") as poolSlice:
44
+ with open(self.jobID_path / self.fileName, "w") as poolSlice:
50
45
  poolSlice.write(xmlSlice)
51
- self.log.info(f"POOL XML Catalogue slice written to {poolXMLCatName}")
46
+ self.log.info(f"POOL XML Catalogue slice written to {self.jobID_path / self.fileName}")
52
47
  try:
53
48
  # Temporary solution to the problem of storing the SE in the Pool XML slice
54
- with open(f"{poolXMLCatName}.temp", "w") as poolSlice_temp:
49
+ with open(self.jobID_path / (self.fileName + ".temp"), "w") as poolSlice_temp:
55
50
  xmlSlice = poolXMLCat.toXML(True)
56
51
  poolSlice_temp.write(xmlSlice)
57
- except Exception as x:
58
- self.log.warn(f"Attempted to write catalog also to {poolXMLCatName}.temp but this failed")
59
- except Exception as x:
60
- self.log.error(str(x))
52
+ except Exception:
53
+ self.log.warn(f"Attempted to write catalog also to {self.fileName}.temp but this failed")
54
+ self.log.exception()
55
+ except Exception:
56
+ self.log.exception()
61
57
  return S_ERROR("Exception during construction of POOL XML slice")
62
58
 
63
59
  return S_OK("POOL XML Slice created")
64
-
65
-
66
- # EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#EOF#
@@ -1,13 +1,18 @@
1
1
  """ Client for the SandboxStore.
2
2
  Will connect to the WorkloadManagement/SandboxStore service.
3
3
  """
4
+ from __future__ import annotations
4
5
 
5
6
  import hashlib
6
7
  import os
7
8
  import re
8
9
  import tarfile
9
10
  import tempfile
11
+ from contextlib import contextmanager
10
12
  from io import BytesIO, StringIO
13
+ from typing import Literal
14
+
15
+ import zstandard
11
16
 
12
17
  from DIRAC import S_ERROR, S_OK, gLogger
13
18
  from DIRAC.ConfigurationSystem.Client.Helpers.Registry import getVOForGroup
@@ -18,9 +23,27 @@ from DIRAC.Core.Utilities.ReturnValues import returnSingleResult
18
23
  from DIRAC.Resources.Storage.StorageElement import StorageElement
19
24
 
20
25
 
26
+ @contextmanager
27
+ def ZstdCompatibleTarFile(tarFileName: os.PathLike, *, mode: Literal["r"] = "r"):
28
+ """Context manager to extend tarfile.open to support zstd compressed files.
29
+
30
+ This is only needed for Python <=3.13.
31
+ """
32
+ with open(tarFileName, "rb") as f:
33
+ magic = f.read(4)
34
+ # Read magic bytes to determine compression format
35
+ if magic.startswith(b"\x28\xb5\x2f\xfd"): # zstd magic number
36
+ dctx = zstandard.ZstdDecompressor()
37
+ with open(tarFileName, "rb") as f, dctx.stream_reader(f) as decompressor:
38
+ with tarfile.open(fileobj=decompressor, mode=f"{mode}|") as tf:
39
+ yield tf
40
+ else:
41
+ with tarfile.open(name=tarFileName, mode=mode) as tf:
42
+ yield tf
43
+
44
+
21
45
  class SandboxStoreClient:
22
46
  __validSandboxTypes = ("Input", "Output")
23
- __smdb = None
24
47
 
25
48
  def __init__(self, rpcClient=None, transferClient=None, smdb=False, **kwargs):
26
49
  """Constructor
@@ -37,21 +60,8 @@ class SandboxStoreClient:
37
60
  self.__transferClient = transferClient
38
61
  self.__kwargs = kwargs
39
62
  self.__vo = None
40
- SandboxStoreClient.__smdb = smdb
41
63
  if "delegatedGroup" in kwargs:
42
64
  self.__vo = getVOForGroup(kwargs["delegatedGroup"])
43
- if SandboxStoreClient.__smdb is True:
44
- try:
45
- from DIRAC.WorkloadManagementSystem.DB.SandboxMetadataDB import SandboxMetadataDB
46
-
47
- SandboxStoreClient.__smdb = SandboxMetadataDB()
48
- result = SandboxStoreClient.__smdb._getConnection() # pylint: disable=protected-access
49
- if not result["OK"]:
50
- SandboxStoreClient.__smdb = False
51
- else:
52
- result["Value"].close()
53
- except (ImportError, RuntimeError, AttributeError):
54
- SandboxStoreClient.__smdb = False
55
65
 
56
66
  def __getRPCClient(self):
57
67
  """Get an RPC client for SB service"""
@@ -206,7 +216,7 @@ class SandboxStoreClient:
206
216
 
207
217
  try:
208
218
  sandboxSize = 0
209
- with tarfile.open(name=tarFileName, mode="r") as tf:
219
+ with ZstdCompatibleTarFile(tarFileName, mode="r") as tf:
210
220
  for tarinfo in tf:
211
221
  tf.extract(tarinfo, path=destinationDir)
212
222
  sandboxSize += tarinfo.size
@@ -227,29 +237,6 @@ class SandboxStoreClient:
227
237
  ##############
228
238
  # Jobs
229
239
 
230
- def assignSandboxesToJob(self, jobId, sbList, ownerName="", ownerGroup=""):
231
- """
232
- Assign sandboxes to a job.
233
- sbList must be a list of sandboxes and relation types
234
- sbList = [ ( "SB:SEName|SEPFN", "Input" ), ( "SB:SEName|SEPFN", "Output" ) ]
235
- """
236
- eId = f"Job:{jobId}"
237
- for sbT in sbList:
238
- if sbT[1] not in self.__validSandboxTypes:
239
- return S_ERROR(f"Invalid Sandbox type {sbT[1]}")
240
- if SandboxStoreClient.__smdb and ownerName and ownerGroup:
241
- return SandboxStoreClient.__smdb.assignSandboxesToEntities({eId: sbList}, ownerName, ownerGroup)
242
- return self.__getRPCClient().assignSandboxesToEntities({eId: sbList}, ownerName, ownerGroup)
243
-
244
- def unassignJobs(self, jobIdList):
245
- """Unassign SB to a job"""
246
- if isinstance(jobIdList, int):
247
- jobIdList = [jobIdList]
248
- entitiesList = []
249
- for jobId in jobIdList:
250
- entitiesList.append(f"Job:{jobId}")
251
- return self.__getRPCClient().unassignEntities(entitiesList)
252
-
253
240
  def downloadSandboxForJob(self, jobId, sbType, destinationPath="", inMemory=False, unpack=True):
254
241
  """Download SB for a job"""
255
242
  result = self.__getRPCClient().getSandboxesAssignedToEntity(f"Job:{jobId}")
@@ -2,11 +2,10 @@
2
2
  methods necessary to communicate with the Workload Management System
3
3
  """
4
4
  import os
5
- from io import StringIO
6
5
  import time
6
+ from io import StringIO
7
7
 
8
- from DIRAC import S_OK, S_ERROR, gLogger
9
-
8
+ from DIRAC import S_ERROR, S_OK, gLogger
10
9
  from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations
11
10
  from DIRAC.Core.Utilities import File
12
11
  from DIRAC.Core.Utilities.ClassAd.ClassAdLight import ClassAd
@@ -1,6 +1,8 @@
1
1
  """Test for WMS clients."""
2
2
  # pylint: disable=protected-access, missing-docstring, invalid-name
3
3
 
4
+ from pathlib import Path
5
+ import shutil
4
6
  import pytest
5
7
 
6
8
  from unittest.mock import MagicMock
@@ -280,3 +282,30 @@ def test_DLI_execute_NoLocal(mocker, dli, mockSE):
280
282
  assert res["Value"]["Failed"]
281
283
  assert "/a/lfn/1.txt" in res["Value"]["Failed"], res
282
284
  assert res["Value"]["Failed"][0] == "/a/lfn/1.txt", res
285
+
286
+
287
+ def test_DLI_execute_jobIDPath(mocker, dli, mockSE):
288
+ """Specify a jobIDPath. Output should be in the jobIDPath directory."""
289
+ mocker.patch("DIRAC.WorkloadManagementSystem.Client.DownloadInputData.gConfig.getValue", return_value=2)
290
+
291
+ # Create the jobIDPath directory
292
+ jobIDPath = Path().cwd() / "job" / "12345"
293
+ jobIDPath.mkdir(parents=True, exist_ok=True)
294
+
295
+ dli.configuration["JobIDPath"] = str(jobIDPath)
296
+
297
+ mocker.patch("DIRAC.WorkloadManagementSystem.Client.DownloadInputData.gConfig.getValue", return_value=2)
298
+ mockObjectSE = mockSE.return_value
299
+ mockObjectSE.getFileMetadata.return_value = S_OK(
300
+ {"Successful": {"/a/lfn/1.txt": {"Cached": 1, "Accessible": 0}}, "Failed": {}}
301
+ )
302
+ dli._downloadFromSE = MagicMock(side_effect=[S_ERROR("Failed to down"), S_OK({"path": jobIDPath / "1.txt"})])
303
+ dli._isCache = MagicMock(return_value=True)
304
+ res = dli.execute(dataToResolve=["/a/lfn/1.txt"])
305
+
306
+ assert res["OK"]
307
+ assert not res["Value"]["Failed"]
308
+ assert "/a/lfn/1.txt" in res["Value"]["Successful"], res
309
+
310
+ # Check that the output path is in the jobIDPath directory
311
+ assert res["Value"]["Successful"]["/a/lfn/1.txt"]["path"] == jobIDPath / "1.txt", res
@@ -263,14 +263,10 @@ Agents
263
263
  # the DN of the certificate proxy used to submit pilots. If not found here, what is in Operations/Pilot section of the CS will be used
264
264
  PilotDN =
265
265
 
266
- # List of sites that will be treated by this SiteDirector (No value can refer to any Site defined in the CS)
267
- Site =
268
- # List of CEs that will be treated by this SiteDirector (No value can refer to any CE defined in the CS)
269
- CEs =
270
- # List of CE types that will be treated by this SiteDirector (No value can refer to any type of CE defined in the CS)
271
- CETypes =
272
- # List of Tags that are required to be present in the CE/Queue definition
273
- Tags =
266
+ # Site = # List of CEs that will be treated by this SiteDirector (No value can refer to any CE defined in the CS)
267
+ # CEs = # List of CE types that will be treated by this SiteDirector (No value can refer to any type of CE defined in the CS)
268
+ # CETypes = # List of Tags that are required to be present in the CE/Queue definition
269
+ # Tags =
274
270
 
275
271
  # How many cycles to skip if queue is not working
276
272
  FailedQueueCycleFactor = 10