DIRAC 9.0.0a54__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 (166) 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 +34 -32
  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 +9 -2
  14. DIRAC/ConfigurationSystem/Client/test/Test_PathFinder.py +41 -1
  15. DIRAC/ConfigurationSystem/private/RefresherBase.py +4 -2
  16. DIRAC/Core/DISET/ServiceReactor.py +11 -3
  17. DIRAC/Core/DISET/private/BaseClient.py +1 -2
  18. DIRAC/Core/DISET/private/Transports/M2SSLTransport.py +9 -7
  19. DIRAC/Core/Security/DiracX.py +12 -7
  20. DIRAC/Core/Security/IAMService.py +4 -3
  21. DIRAC/Core/Security/ProxyInfo.py +9 -5
  22. DIRAC/Core/Security/test/test_diracx_token_from_pem.py +161 -0
  23. DIRAC/Core/Tornado/Client/ClientSelector.py +4 -1
  24. DIRAC/Core/Tornado/Server/TornadoService.py +1 -1
  25. DIRAC/Core/Utilities/ClassAd/ClassAdLight.py +4 -290
  26. DIRAC/Core/Utilities/DErrno.py +5 -309
  27. DIRAC/Core/Utilities/Extensions.py +10 -1
  28. DIRAC/Core/Utilities/Graphs/GraphData.py +1 -1
  29. DIRAC/Core/Utilities/JDL.py +1 -195
  30. DIRAC/Core/Utilities/List.py +1 -124
  31. DIRAC/Core/Utilities/MySQL.py +101 -97
  32. DIRAC/Core/Utilities/Os.py +32 -1
  33. DIRAC/Core/Utilities/Platform.py +2 -107
  34. DIRAC/Core/Utilities/ReturnValues.py +7 -252
  35. DIRAC/Core/Utilities/StateMachine.py +12 -178
  36. DIRAC/Core/Utilities/TimeUtilities.py +10 -253
  37. DIRAC/Core/Utilities/test/Test_JDL.py +0 -3
  38. DIRAC/Core/Utilities/test/Test_Profiler.py +20 -20
  39. DIRAC/Core/scripts/dirac_agent.py +1 -1
  40. DIRAC/Core/scripts/dirac_apptainer_exec.py +16 -7
  41. DIRAC/Core/scripts/dirac_platform.py +1 -92
  42. DIRAC/DataManagementSystem/Agent/FTS3Agent.py +8 -7
  43. DIRAC/DataManagementSystem/Agent/RequestOperations/RemoveFile.py +7 -6
  44. DIRAC/DataManagementSystem/Client/FTS3Job.py +71 -34
  45. DIRAC/DataManagementSystem/DB/FTS3DB.py +3 -0
  46. DIRAC/DataManagementSystem/DB/FileCatalogComponents/DatasetManager/DatasetManager.py +1 -1
  47. DIRAC/DataManagementSystem/Utilities/DMSHelpers.py +6 -2
  48. DIRAC/DataManagementSystem/scripts/dirac_dms_create_moving_request.py +2 -0
  49. DIRAC/DataManagementSystem/scripts/dirac_dms_protocol_matrix.py +0 -1
  50. DIRAC/FrameworkSystem/Client/ComponentInstaller.py +4 -2
  51. DIRAC/FrameworkSystem/DB/ProxyDB.py +9 -5
  52. DIRAC/FrameworkSystem/Utilities/TokenManagementUtilities.py +3 -2
  53. DIRAC/FrameworkSystem/Utilities/diracx.py +2 -74
  54. DIRAC/FrameworkSystem/private/authorization/AuthServer.py +2 -2
  55. DIRAC/FrameworkSystem/scripts/dirac_login.py +2 -2
  56. DIRAC/FrameworkSystem/scripts/dirac_proxy_init.py +1 -1
  57. DIRAC/Interfaces/API/Dirac.py +27 -13
  58. DIRAC/Interfaces/API/DiracAdmin.py +42 -7
  59. DIRAC/Interfaces/API/Job.py +1 -0
  60. DIRAC/Interfaces/scripts/dirac_admin_allow_site.py +7 -1
  61. DIRAC/Interfaces/scripts/dirac_admin_ban_site.py +7 -1
  62. DIRAC/Interfaces/scripts/dirac_wms_job_parameters.py +0 -1
  63. DIRAC/MonitoringSystem/Client/Types/WMSHistory.py +4 -0
  64. DIRAC/MonitoringSystem/Client/WebAppClient.py +26 -0
  65. DIRAC/MonitoringSystem/ConfigTemplate.cfg +9 -0
  66. DIRAC/MonitoringSystem/DB/MonitoringDB.py +6 -25
  67. DIRAC/MonitoringSystem/Service/MonitoringHandler.py +0 -33
  68. DIRAC/MonitoringSystem/Service/WebAppHandler.py +599 -0
  69. DIRAC/MonitoringSystem/private/MainReporter.py +0 -3
  70. DIRAC/ProductionSystem/scripts/dirac_prod_get_trans.py +2 -3
  71. DIRAC/RequestManagementSystem/Agent/RequestExecutingAgent.py +8 -6
  72. DIRAC/RequestManagementSystem/ConfigTemplate.cfg +6 -6
  73. DIRAC/RequestManagementSystem/DB/test/RMSTestScenari.py +2 -0
  74. DIRAC/ResourceStatusSystem/Client/SiteStatus.py +4 -2
  75. DIRAC/ResourceStatusSystem/Command/FreeDiskSpaceCommand.py +3 -1
  76. DIRAC/ResourceStatusSystem/Utilities/CSHelpers.py +2 -31
  77. DIRAC/ResourceStatusSystem/scripts/dirac_rss_set_status.py +18 -4
  78. DIRAC/Resources/Catalog/RucioFileCatalogClient.py +1 -1
  79. DIRAC/Resources/Computing/AREXComputingElement.py +19 -3
  80. DIRAC/Resources/Computing/BatchSystems/Condor.py +126 -108
  81. DIRAC/Resources/Computing/BatchSystems/SLURM.py +5 -1
  82. DIRAC/Resources/Computing/BatchSystems/test/Test_SLURM.py +46 -0
  83. DIRAC/Resources/Computing/HTCondorCEComputingElement.py +37 -43
  84. DIRAC/Resources/Computing/SingularityComputingElement.py +6 -1
  85. DIRAC/Resources/Computing/test/Test_HTCondorCEComputingElement.py +67 -49
  86. DIRAC/Resources/Computing/test/Test_PoolComputingElement.py +2 -1
  87. DIRAC/Resources/IdProvider/CheckInIdProvider.py +13 -0
  88. DIRAC/Resources/IdProvider/IdProviderFactory.py +11 -3
  89. DIRAC/Resources/Storage/StorageBase.py +4 -2
  90. DIRAC/Resources/Storage/StorageElement.py +4 -4
  91. DIRAC/TransformationSystem/Agent/TaskManagerAgentBase.py +10 -16
  92. DIRAC/TransformationSystem/Agent/TransformationAgent.py +22 -1
  93. DIRAC/TransformationSystem/Agent/TransformationCleaningAgent.py +15 -15
  94. DIRAC/TransformationSystem/Client/Transformation.py +2 -1
  95. DIRAC/TransformationSystem/Client/TransformationClient.py +0 -7
  96. DIRAC/TransformationSystem/Client/Utilities.py +9 -0
  97. DIRAC/TransformationSystem/Service/TransformationManagerHandler.py +0 -336
  98. DIRAC/TransformationSystem/Utilities/ReplicationCLIParameters.py +3 -3
  99. DIRAC/TransformationSystem/scripts/dirac_production_runjoblocal.py +2 -4
  100. DIRAC/TransformationSystem/test/Test_replicationTransformation.py +5 -6
  101. DIRAC/Workflow/Modules/test/Test_Modules.py +5 -0
  102. DIRAC/WorkloadManagementSystem/Agent/JobAgent.py +1 -5
  103. DIRAC/WorkloadManagementSystem/Agent/JobCleaningAgent.py +11 -7
  104. DIRAC/WorkloadManagementSystem/Agent/PilotSyncAgent.py +4 -3
  105. DIRAC/WorkloadManagementSystem/Agent/PushJobAgent.py +13 -13
  106. DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py +10 -13
  107. DIRAC/WorkloadManagementSystem/Agent/StalledJobAgent.py +18 -51
  108. DIRAC/WorkloadManagementSystem/Agent/StatesAccountingAgent.py +41 -1
  109. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobAgent.py +2 -0
  110. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobCleaningAgent.py +7 -9
  111. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PushJobAgent.py +1 -0
  112. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_SiteDirector.py +8 -2
  113. DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_StalledJobAgent.py +4 -5
  114. DIRAC/WorkloadManagementSystem/Client/DownloadInputData.py +7 -5
  115. DIRAC/WorkloadManagementSystem/Client/JobMonitoringClient.py +10 -11
  116. DIRAC/WorkloadManagementSystem/Client/JobState/JobManifest.py +32 -261
  117. DIRAC/WorkloadManagementSystem/Client/JobStateUpdateClient.py +3 -0
  118. DIRAC/WorkloadManagementSystem/Client/JobStatus.py +8 -152
  119. DIRAC/WorkloadManagementSystem/Client/SandboxStoreClient.py +25 -38
  120. DIRAC/WorkloadManagementSystem/Client/WMSClient.py +2 -3
  121. DIRAC/WorkloadManagementSystem/Client/test/Test_Client_DownloadInputData.py +29 -0
  122. DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg +4 -8
  123. DIRAC/WorkloadManagementSystem/DB/JobDB.py +40 -69
  124. DIRAC/WorkloadManagementSystem/DB/JobDBUtils.py +18 -147
  125. DIRAC/WorkloadManagementSystem/DB/JobParametersDB.py +9 -9
  126. DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py +3 -2
  127. DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py +28 -39
  128. DIRAC/WorkloadManagementSystem/DB/StatusUtils.py +125 -0
  129. DIRAC/WorkloadManagementSystem/DB/tests/Test_JobDB.py +1 -1
  130. DIRAC/WorkloadManagementSystem/DB/tests/Test_StatusUtils.py +28 -0
  131. DIRAC/WorkloadManagementSystem/Executor/JobSanity.py +3 -3
  132. DIRAC/WorkloadManagementSystem/FutureClient/JobStateUpdateClient.py +2 -14
  133. DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapper.py +14 -9
  134. DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapper.py +36 -10
  135. DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapperTemplate.py +4 -0
  136. DIRAC/WorkloadManagementSystem/Service/JobManagerHandler.py +33 -154
  137. DIRAC/WorkloadManagementSystem/Service/JobMonitoringHandler.py +5 -323
  138. DIRAC/WorkloadManagementSystem/Service/JobStateUpdateHandler.py +0 -16
  139. DIRAC/WorkloadManagementSystem/Service/PilotManagerHandler.py +6 -102
  140. DIRAC/WorkloadManagementSystem/Service/SandboxStoreHandler.py +5 -51
  141. DIRAC/WorkloadManagementSystem/Service/WMSAdministratorHandler.py +16 -79
  142. DIRAC/WorkloadManagementSystem/Utilities/JobModel.py +28 -199
  143. DIRAC/WorkloadManagementSystem/Utilities/JobParameters.py +65 -3
  144. DIRAC/WorkloadManagementSystem/Utilities/JobStatusUtility.py +2 -64
  145. DIRAC/WorkloadManagementSystem/Utilities/ParametricJob.py +7 -171
  146. DIRAC/WorkloadManagementSystem/Utilities/PilotCStoJSONSynchronizer.py +73 -7
  147. DIRAC/WorkloadManagementSystem/Utilities/PilotWrapper.py +2 -0
  148. DIRAC/WorkloadManagementSystem/Utilities/RemoteRunner.py +16 -0
  149. DIRAC/WorkloadManagementSystem/Utilities/Utils.py +36 -1
  150. DIRAC/WorkloadManagementSystem/Utilities/jobAdministration.py +15 -0
  151. DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobModel.py +1 -5
  152. DIRAC/WorkloadManagementSystem/Utilities/test/Test_ParametricJob.py +45 -128
  153. DIRAC/WorkloadManagementSystem/Utilities/test/Test_PilotWrapper.py +16 -0
  154. DIRAC/__init__.py +55 -54
  155. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/METADATA +6 -4
  156. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/RECORD +160 -160
  157. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/WHEEL +1 -1
  158. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/entry_points.txt +0 -3
  159. DIRAC/Core/Utilities/test/Test_List.py +0 -150
  160. DIRAC/Core/Utilities/test/Test_Time.py +0 -88
  161. DIRAC/TransformationSystem/scripts/dirac_transformation_archive.py +0 -30
  162. DIRAC/TransformationSystem/scripts/dirac_transformation_clean.py +0 -30
  163. DIRAC/TransformationSystem/scripts/dirac_transformation_remove_output.py +0 -30
  164. DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobManager.py +0 -58
  165. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/licenses/LICENSE +0 -0
  166. {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/top_level.txt +0 -0
@@ -4,17 +4,13 @@
4
4
  The following methods are available in the Service interface
5
5
  """
6
6
 
7
- import DIRAC.Core.Utilities.TimeUtilities as TimeUtilities
8
7
  from DIRAC import S_ERROR, S_OK
9
8
  from DIRAC.ConfigurationSystem.Client.Helpers import Registry
10
- from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations
11
9
  from DIRAC.Core.DISET.RequestHandler import RequestHandler
12
10
  from DIRAC.Core.Utilities.DEncode import ignoreEncodeWarning
13
11
  from DIRAC.Core.Utilities.JEncode import strToIntDict
14
12
  from DIRAC.Core.Utilities.ObjectLoader import ObjectLoader
15
- from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations
16
- from DIRAC.WorkloadManagementSystem.Client.PilotManagerClient import PilotManagerClient
17
- from DIRAC.WorkloadManagementSystem.Service.JobPolicy import RIGHT_GET_INFO, JobPolicy
13
+ from DIRAC.WorkloadManagementSystem.Utilities.JobParameters import getJobParameters
18
14
 
19
15
 
20
16
  class JobMonitoringHandlerMixin:
@@ -40,51 +36,12 @@ class JobMonitoringHandlerMixin:
40
36
  return result
41
37
  cls.elasticJobParametersDB = result["Value"](parentLogger=cls.log)
42
38
 
43
- cls.pilotManager = PilotManagerClient()
44
39
  return S_OK()
45
40
 
46
41
  def initializeRequest(self):
47
42
  credDict = self.getRemoteCredentials()
48
43
  self.vo = credDict.get("VO", Registry.getVOForGroup(credDict["group"]))
49
44
 
50
- @classmethod
51
- def parseSelectors(cls, selectDict=None):
52
- """Parse selectors before DB query
53
-
54
- :param dict selectDict: selectors
55
-
56
- :return: str, str, dict -- start/end date, selectors
57
- """
58
- selectDict = selectDict or {}
59
-
60
- # Get time period
61
- startDate = selectDict.get("FromDate", None)
62
- if startDate:
63
- del selectDict["FromDate"]
64
- # For backward compatibility
65
- if startDate is None:
66
- startDate = selectDict.get("LastUpdate", None)
67
- if startDate:
68
- del selectDict["LastUpdate"]
69
- endDate = selectDict.get("ToDate", None)
70
- if endDate:
71
- del selectDict["ToDate"]
72
-
73
- # Provide JobID bound to a specific PilotJobReference
74
- # There is no reason to have both PilotJobReference and JobID in selectDict
75
- # If that occurs, use the JobID instead of the PilotJobReference
76
- pilotJobRefs = selectDict.get("PilotJobReference")
77
- if pilotJobRefs:
78
- del selectDict["PilotJobReference"]
79
- if not selectDict.get("JobID"):
80
- for pilotJobRef in [pilotJobRefs] if isinstance(pilotJobRefs, str) else pilotJobRefs:
81
- res = cls.pilotManager.getPilotInfo(pilotJobRef)
82
- if res["OK"] and "Jobs" in res["Value"][pilotJobRef]:
83
- selectDict["JobID"] = selectDict.get("JobID", [])
84
- selectDict["JobID"].extend(res["Value"][pilotJobRef]["Jobs"])
85
-
86
- return startDate, endDate, selectDict
87
-
88
45
  @classmethod
89
46
  def getJobsAttributes(cls, *args, **kwargs):
90
47
  """Utility function for unpacking"""
@@ -93,82 +50,6 @@ class JobMonitoringHandlerMixin:
93
50
  return res
94
51
  return S_OK(strToIntDict(res["Value"]))
95
52
 
96
- ##############################################################################
97
- types_getApplicationStates = []
98
-
99
- @classmethod
100
- def export_getApplicationStates(cls, condDict=None, older=None, newer=None):
101
- """Return Distinct Values of ApplicationStatus job Attribute in WMS"""
102
- return cls.jobDB.getDistinctJobAttributes("ApplicationStatus", condDict, older, newer)
103
-
104
- ##############################################################################
105
- types_getJobTypes = []
106
-
107
- @classmethod
108
- def export_getJobTypes(cls, condDict=None, older=None, newer=None):
109
- """Return Distinct Values of JobType job Attribute in WMS"""
110
- return cls.jobDB.getDistinctJobAttributes("JobType", condDict, older, newer)
111
-
112
- ##############################################################################
113
- types_getOwners = []
114
-
115
- @classmethod
116
- def export_getOwners(cls, condDict=None, older=None, newer=None):
117
- """
118
- Return Distinct Values of Owner job Attribute in WMS
119
- """
120
- return cls.jobDB.getDistinctJobAttributes("Owner", condDict, older, newer)
121
-
122
- ##############################################################################
123
- types_getOwnerGroup = []
124
-
125
- @classmethod
126
- def export_getOwnerGroup(cls):
127
- """
128
- Return Distinct Values of OwnerGroup from the JobDB
129
- """
130
- return cls.jobDB.getDistinctJobAttributes("OwnerGroup")
131
-
132
- ##############################################################################
133
- types_getJobGroups = []
134
-
135
- @classmethod
136
- def export_getJobGroups(cls, condDict=None, older=None, cutDate=None):
137
- """
138
- Return Distinct Values of ProductionId job Attribute in WMS
139
- """
140
- return cls.jobDB.getDistinctJobAttributes("JobGroup", condDict, older, newer=cutDate)
141
-
142
- ##############################################################################
143
- types_getSites = []
144
-
145
- @classmethod
146
- def export_getSites(cls, condDict=None, older=None, newer=None):
147
- """
148
- Return Distinct Values of Site job Attribute in WMS
149
- """
150
- return cls.jobDB.getDistinctJobAttributes("Site", condDict, older, newer)
151
-
152
- ##############################################################################
153
- types_getStates = []
154
-
155
- @classmethod
156
- def export_getStates(cls, condDict=None, older=None, newer=None):
157
- """
158
- Return Distinct Values of Status job Attribute in WMS
159
- """
160
- return cls.jobDB.getDistinctJobAttributes("Status", condDict, older, newer)
161
-
162
- ##############################################################################
163
- types_getMinorStates = []
164
-
165
- @classmethod
166
- def export_getMinorStates(cls, condDict=None, older=None, newer=None):
167
- """
168
- Return Distinct Values of Minor Status job Attribute in WMS
169
- """
170
- return cls.jobDB.getDistinctJobAttributes("MinorStatus", condDict, older, newer)
171
-
172
53
  ##############################################################################
173
54
  types_getJobs = []
174
55
 
@@ -189,36 +70,6 @@ class JobMonitoringHandlerMixin:
189
70
 
190
71
  return cls.jobDB.selectJobs(attrDict, newer=cutDate)
191
72
 
192
- ##############################################################################
193
- types_getCounters = [list]
194
-
195
- @classmethod
196
- def export_getCounters(cls, attrList, attrDict=None, cutDate=""):
197
- """
198
- Retrieve list of distinct attributes values from attrList
199
- with attrDict as condition.
200
- For each set of distinct values, count number of occurences.
201
- Return a list. Each item is a list with 2 items, the list of distinct
202
- attribute values and the counter
203
- """
204
-
205
- _, _, attrDict = cls.parseSelectors(attrDict)
206
- return cls.jobDB.getCounters("Jobs", attrList, attrDict, newer=str(cutDate), timeStamp="LastUpdateTime")
207
-
208
- ##############################################################################
209
- types_getJobOwner = [int]
210
-
211
- @classmethod
212
- def export_getJobOwner(cls, jobID):
213
- return cls.jobDB.getJobAttribute(jobID, "Owner")
214
-
215
- ##############################################################################
216
- types_getJobSite = [int]
217
-
218
- @classmethod
219
- def export_getJobSite(cls, jobID):
220
- return cls.jobDB.getJobAttribute(jobID, "Site")
221
-
222
73
  ##############################################################################
223
74
  types_getJobJDL = [int, bool]
224
75
 
@@ -233,14 +84,6 @@ class JobMonitoringHandlerMixin:
233
84
  def export_getJobLoggingInfo(cls, jobID):
234
85
  return cls.jobLoggingDB.getJobLoggingInfo(jobID)
235
86
 
236
- ##############################################################################
237
- types_getJobsParameters = [[str, int, list], list]
238
-
239
- @classmethod
240
- @ignoreEncodeWarning
241
- def export_getJobsParameters(cls, jobIDs, parameters):
242
- return cls.getJobsAttributes(jobIDs, parameters)
243
-
244
87
  ##############################################################################
245
88
  types_getJobsStates = [[str, int, list]]
246
89
 
@@ -295,122 +138,6 @@ class JobMonitoringHandlerMixin:
295
138
  def export_getJobsSummary(cls, jobIDs):
296
139
  return cls.getJobsAttributes(jobIDs)
297
140
 
298
- ##############################################################################
299
- types_getJobPageSummaryWeb = [dict, list, int, int]
300
-
301
- def export_getJobPageSummaryWeb(self, selectDict, sortList, startItem, maxItems, selectJobs=True):
302
- """Get the summary of the job information for a given page in the
303
- job monitor in a generic format
304
- """
305
-
306
- resultDict = {}
307
-
308
- startDate, endDate, selectDict = self.parseSelectors(selectDict)
309
-
310
- # initialize jobPolicy
311
- credDict = self.getRemoteCredentials()
312
- owner = credDict["username"]
313
- ownerGroup = credDict["group"]
314
- operations = Operations(group=ownerGroup)
315
- globalJobsInfo = operations.getValue("/Services/JobMonitoring/GlobalJobsInfo", True)
316
- jobPolicy = JobPolicy(owner, ownerGroup, globalJobsInfo)
317
- jobPolicy.jobDB = self.jobDB
318
- result = jobPolicy.getControlledUsers(RIGHT_GET_INFO)
319
- if not result["OK"]:
320
- return result
321
- if not result["Value"]:
322
- return S_ERROR(f"User and group combination has no job rights ({owner!r}, {ownerGroup!r})")
323
- if result["Value"] != "ALL":
324
- selectDict[("Owner", "OwnerGroup")] = result["Value"]
325
-
326
- # Sorting instructions. Only one for the moment.
327
- if sortList:
328
- orderAttribute = sortList[0][0] + ":" + sortList[0][1]
329
- else:
330
- orderAttribute = None
331
-
332
- result = self.jobDB.getCounters(
333
- "Jobs", ["Status"], selectDict, newer=startDate, older=endDate, timeStamp="LastUpdateTime"
334
- )
335
- if not result["OK"]:
336
- return result
337
-
338
- statusDict = {}
339
- nJobs = 0
340
- for stDict, count in result["Value"]:
341
- nJobs += count
342
- statusDict[stDict["Status"]] = count
343
-
344
- resultDict["TotalRecords"] = nJobs
345
- if nJobs == 0:
346
- return S_OK(resultDict)
347
-
348
- resultDict["Extras"] = statusDict
349
-
350
- if selectJobs:
351
- iniJob = startItem
352
- if iniJob >= nJobs:
353
- return S_ERROR("Item number out of range")
354
-
355
- result = self.jobDB.selectJobs(
356
- selectDict, orderAttribute=orderAttribute, newer=startDate, older=endDate, limit=(maxItems, iniJob)
357
- )
358
- if not result["OK"]:
359
- return result
360
-
361
- summaryJobList = result["Value"]
362
- if not globalJobsInfo:
363
- validJobs, _invalidJobs, _nonauthJobs, _ownJobs = jobPolicy.evaluateJobRights(
364
- summaryJobList, RIGHT_GET_INFO
365
- )
366
- summaryJobList = validJobs
367
-
368
- result = self.getJobsAttributes(summaryJobList)
369
- if not result["OK"]:
370
- return result
371
-
372
- summaryDict = result["Value"]
373
- # If no jobs can be selected after the properties check
374
- if not summaryDict:
375
- return S_OK(resultDict)
376
-
377
- # Evaluate last sign of life time
378
- for jobDict in summaryDict.values():
379
- if not jobDict.get("HeartBeatTime") or jobDict["HeartBeatTime"] == "None":
380
- jobDict["LastSignOfLife"] = jobDict["LastUpdateTime"]
381
- else:
382
- jobDict["LastSignOfLife"] = jobDict["HeartBeatTime"]
383
-
384
- # prepare the standard structure now
385
- # This should be faster than making a list of values()
386
- for jobDict in summaryDict.values():
387
- paramNames = list(jobDict)
388
- break
389
- records = [list(jobDict.values()) for jobDict in summaryDict.values()]
390
-
391
- resultDict["ParameterNames"] = paramNames
392
- resultDict["Records"] = records
393
-
394
- return S_OK(resultDict)
395
-
396
- ##############################################################################
397
- types_getJobStats = [str, dict]
398
-
399
- @classmethod
400
- def export_getJobStats(cls, attribute, selectDict):
401
- """Get job statistics distribution per attribute value with a given selection"""
402
- startDate, endDate, selectDict = cls.parseSelectors(selectDict)
403
- result = cls.jobDB.getCounters(
404
- "Jobs", [attribute], selectDict, newer=startDate, older=endDate, timeStamp="LastUpdateTime"
405
- )
406
- if not result["OK"]:
407
- return result
408
- resultDict = {}
409
- for cDict, count in result["Value"]:
410
- resultDict[cDict[attribute]] = count
411
-
412
- return S_OK(resultDict)
413
-
414
141
  ##############################################################################
415
142
  types_getJobParameter = [[str, int], str]
416
143
 
@@ -420,18 +147,11 @@ class JobMonitoringHandlerMixin:
420
147
  :param str/int jobID: one single Job ID
421
148
  :param str parName: one single parameter name
422
149
  """
423
- res = self.elasticJobParametersDB.getJobParameters(int(jobID), self.vo, [parName])
150
+ res = getJobParameters([int(jobID)], parName, self.vo or "")
424
151
  if not res["OK"]:
425
152
  return res
426
153
  return S_OK(res["Value"].get(int(jobID), {}))
427
154
 
428
- ##############################################################################
429
- types_getJobOptParameters = [int]
430
-
431
- @classmethod
432
- def export_getJobOptParameters(cls, jobID):
433
- return cls.jobDB.getJobOptParameters(jobID)
434
-
435
155
  ##############################################################################
436
156
  types_getJobParameters = [[str, int, list]]
437
157
 
@@ -439,41 +159,13 @@ class JobMonitoringHandlerMixin:
439
159
  def export_getJobParameters(self, jobIDs, parName=None):
440
160
  """
441
161
  :param str/int/list jobIDs: one single job ID or a list of them
442
- :param str parName: one single parameter name, a list or None (meaning all of them)
162
+ :param str parName: one single parameter name, or None (meaning all of them)
443
163
  """
444
164
  if not isinstance(jobIDs, list):
445
165
  jobIDs = [jobIDs]
446
166
  jobIDs = [int(jobID) for jobID in jobIDs]
447
- res = self.elasticJobParametersDB.getJobParameters(jobIDs, self.vo, parName)
448
- if not res["OK"]:
449
- return res
450
- parameters = res["Value"]
451
167
 
452
- # Need anyway to get also from JobDB, for those jobs with parameters registered in MySQL or in both backends
453
- res = self.jobDB.getJobParameters(jobIDs, parName)
454
- if not res["OK"]:
455
- return res
456
- parametersM = res["Value"]
457
-
458
- # and now combine
459
- final = dict(parametersM)
460
- # if job in JobDB, update with parameters from ES if any
461
- for jobID in final:
462
- final[jobID].update(parameters.get(jobID, {}))
463
- # if job in ES and not in JobDB, take ES
464
- for jobID in parameters:
465
- if jobID not in final:
466
- final[jobID] = parameters[jobID]
467
- return S_OK(final)
468
-
469
- ##############################################################################
470
- types_getAtticJobParameters = [int]
471
-
472
- @classmethod
473
- def export_getAtticJobParameters(cls, jobID, parameters=None, rescheduleCycle=-1):
474
- if not parameters:
475
- parameters = []
476
- return cls.jobDB.getAtticJobParameters(jobID, parameters, rescheduleCycle)
168
+ return getJobParameters(jobIDs, parName, self.vo or "")
477
169
 
478
170
  ##############################################################################
479
171
  types_getJobAttributes = [int]
@@ -499,13 +191,6 @@ class JobMonitoringHandlerMixin:
499
191
 
500
192
  return cls.jobDB.getJobAttribute(jobID, attribute)
501
193
 
502
- ##############################################################################
503
- types_getSiteSummary = []
504
-
505
- @classmethod
506
- def export_getSiteSummary(cls):
507
- return cls.jobDB.getSiteSummary()
508
-
509
194
  ##############################################################################
510
195
  types_getJobHeartBeatData = [int]
511
196
 
@@ -514,7 +199,7 @@ class JobMonitoringHandlerMixin:
514
199
  return cls.jobDB.getHeartBeatData(jobID)
515
200
 
516
201
  ##############################################################################
517
- types_getInputData = [int]
202
+ types_getInputData = [(int, list)]
518
203
 
519
204
  @classmethod
520
205
  def export_getInputData(cls, jobID):
@@ -522,9 +207,6 @@ class JobMonitoringHandlerMixin:
522
207
  return cls.jobDB.getInputData(jobID)
523
208
 
524
209
 
525
- ##############################################################################
526
-
527
-
528
210
  class JobMonitoringHandler(JobMonitoringHandlerMixin, RequestHandler):
529
211
  def initialize(self):
530
212
  return self.initializeRequest()
@@ -128,22 +128,6 @@ class JobStateUpdateHandlerMixin:
128
128
  """Allows the site attribute to be set for a job specified by its jobID."""
129
129
  return cls.jobDB.setJobAttribute(int(jobID), "Site", site)
130
130
 
131
- ###########################################################################
132
- types_setJobFlag = [[str, int], str]
133
-
134
- @classmethod
135
- def export_setJobFlag(cls, jobID, flag):
136
- """Set job flag for job with jobID"""
137
- return cls.jobDB.setJobAttribute(int(jobID), flag, "True")
138
-
139
- ###########################################################################
140
- types_unsetJobFlag = [[str, int], str]
141
-
142
- @classmethod
143
- def export_unsetJobFlag(cls, jobID, flag):
144
- """Unset job flag for job with jobID"""
145
- return cls.jobDB.setJobAttribute(int(jobID), flag, "False")
146
-
147
131
  ###########################################################################
148
132
  types_setJobApplicationStatus = [[str, int], str, str]
149
133
 
@@ -13,7 +13,6 @@ from DIRAC.WorkloadManagementSystem.Client import PilotStatus
13
13
  from DIRAC.WorkloadManagementSystem.Service.WMSUtilities import (
14
14
  getPilotCE,
15
15
  getPilotRef,
16
- killPilotsInQueues,
17
16
  setPilotCredentials,
18
17
  )
19
18
 
@@ -94,10 +93,10 @@ class PilotManagerHandler(RequestHandler):
94
93
 
95
94
  result = self.pilotAgentsDB.getPilotInfo(pilotReference)
96
95
  if not result["OK"]:
97
- self.log.error("Failed to get info for pilot", result["Message"])
96
+ self.log.error("Failed to get info for pilot", f"{pilotReference}: {result['Message']}")
98
97
  return S_ERROR("Failed to get info for pilot")
99
98
  if not result["Value"]:
100
- self.log.warn("The pilot info is empty", pilotReference)
99
+ self.log.warn("The pilot info is empty for", pilotReference)
101
100
  return S_ERROR("Pilot info is empty")
102
101
 
103
102
  pilotDict = result["Value"][pilotReference]
@@ -106,11 +105,14 @@ class PilotManagerHandler(RequestHandler):
106
105
  # classic logs first, by default
107
106
  funcs = [self._getPilotOutput, self._getRemotePilotOutput]
108
107
  if remote:
108
+ self.log.info("Trying to retrieve output of pilot", f"{pilotReference} remotely first")
109
109
  funcs.reverse()
110
110
 
111
111
  result = funcs[0](pilotReference, pilotDict)
112
112
  if not result["OK"]:
113
- self.log.warn("Pilot log retrieval failed (first attempt), remote ?", remote)
113
+ self.log.warn(
114
+ "Failed getting output for pilot", f"{pilotReference}. Will try another approach: {result['Message']}"
115
+ )
114
116
  result = funcs[1](pilotReference, pilotDict)
115
117
  return result
116
118
  else:
@@ -275,37 +277,6 @@ class PilotManagerHandler(RequestHandler):
275
277
 
276
278
  return cls.pilotAgentsDB.getPilotSummary(startdate, enddate)
277
279
 
278
- ##############################################################################
279
- types_getPilotMonitorWeb = [dict, list, int, int]
280
-
281
- @classmethod
282
- def export_getPilotMonitorWeb(cls, selectDict, sortList, startItem, maxItems):
283
- """Get the summary of the pilot information for a given page in the
284
- pilot monitor in a generic format
285
- """
286
-
287
- return cls.pilotAgentsDB.getPilotMonitorWeb(selectDict, sortList, startItem, maxItems)
288
-
289
- ##############################################################################
290
- types_getPilotMonitorSelectors = []
291
-
292
- @classmethod
293
- def export_getPilotMonitorSelectors(cls):
294
- """Get all the distinct selector values for the Pilot Monitor web portal page"""
295
-
296
- return cls.pilotAgentsDB.getPilotMonitorSelectors()
297
-
298
- ##############################################################################
299
- types_getPilotSummaryWeb = [dict, list, int, int]
300
-
301
- @classmethod
302
- def export_getPilotSummaryWeb(cls, selectDict, sortList, startItem, maxItems):
303
- """Get the summary of the pilot information for a given page in the
304
- pilot monitor in a generic format
305
- """
306
-
307
- return cls.pilotAgentsDB.getPilotSummaryWeb(selectDict, sortList, startItem, maxItems)
308
-
309
280
  ##############################################################################
310
281
  types_getGroupedPilotSummary = [list]
311
282
 
@@ -332,35 +303,6 @@ class PilotManagerHandler(RequestHandler):
332
303
 
333
304
  return cls.pilotAgentsDB.getPilotInfo(pilotID=result["Value"])
334
305
 
335
- ##############################################################################
336
- types_killPilot = [[str, list]]
337
-
338
- @classmethod
339
- def export_killPilot(cls, pilotRefList):
340
- """Kill the specified pilots"""
341
- # Make a list if it is not yet
342
- if isinstance(pilotRefList, str):
343
- pilotRefList = [pilotRefList]
344
-
345
- # Regroup pilots per site
346
- pilotRefDict = {}
347
- for pilotReference in pilotRefList:
348
- result = cls.pilotAgentsDB.getPilotInfo(pilotReference)
349
- if not result["OK"] or not result["Value"]:
350
- return S_ERROR(f"Failed to get info for pilot {pilotReference}")
351
-
352
- pilotDict = result["Value"][pilotReference]
353
- queue = "@@@".join(
354
- [pilotDict["VO"], pilotDict["GridSite"], pilotDict["DestinationSite"], pilotDict["Queue"]]
355
- )
356
- gridType = pilotDict["GridType"]
357
- pilotRefDict.setdefault(queue, {})
358
- pilotRefDict[queue].setdefault("PilotList", [])
359
- pilotRefDict[queue]["PilotList"].append(pilotReference)
360
- pilotRefDict[queue]["GridType"] = gridType
361
-
362
- return killPilotsInQueues(pilotRefDict)
363
-
364
306
  ##############################################################################
365
307
  types_setJobForPilot = [[str, int], str]
366
308
 
@@ -416,44 +358,6 @@ class PilotManagerHandler(RequestHandler):
416
358
  return cls.pilotAgentsDB.countPilots(condDict, older, newer, timeStamp)
417
359
 
418
360
  ##########################################################################################
419
- types_getCounters = [str, list, dict]
420
-
421
- @classmethod
422
- def export_getCounters(cls, table, keys, condDict, newer=None, timeStamp="SubmissionTime"):
423
- """Set the pilot agent status"""
424
-
425
- return cls.pilotAgentsDB.getCounters(table, keys, condDict, newer=newer, timeStamp=timeStamp)
426
-
427
- ##############################################################################
428
- types_getPilotStatistics = [str, dict]
429
-
430
- @classmethod
431
- def export_getPilotStatistics(cls, attribute, selectDict):
432
- """Get pilot statistics distribution per attribute value with a given selection"""
433
-
434
- startDate = selectDict.get("FromDate", None)
435
- if startDate:
436
- del selectDict["FromDate"]
437
-
438
- if startDate is None:
439
- startDate = selectDict.get("LastUpdate", None)
440
- if startDate:
441
- del selectDict["LastUpdate"]
442
- endDate = selectDict.get("ToDate", None)
443
- if endDate:
444
- del selectDict["ToDate"]
445
-
446
- result = cls.pilotAgentsDB.getCounters(
447
- "PilotAgents", [attribute], selectDict, newer=startDate, older=endDate, timeStamp="LastUpdateTime"
448
- )
449
- statistics = {}
450
- if result["OK"]:
451
- for status, count in result["Value"]:
452
- statistics[status[attribute]] = count
453
-
454
- return S_OK(statistics)
455
-
456
- ##############################################################################
457
361
  types_deletePilots = [[list, str, int]]
458
362
 
459
363
  @classmethod