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.
- DIRAC/AccountingSystem/Client/AccountingCLI.py +0 -140
- DIRAC/AccountingSystem/Client/DataStoreClient.py +0 -13
- DIRAC/AccountingSystem/Client/Types/BaseAccountingType.py +0 -7
- DIRAC/AccountingSystem/ConfigTemplate.cfg +0 -5
- DIRAC/AccountingSystem/Service/DataStoreHandler.py +0 -72
- DIRAC/ConfigurationSystem/Client/Helpers/CSGlobals.py +0 -9
- DIRAC/ConfigurationSystem/Client/Helpers/Registry.py +34 -32
- DIRAC/ConfigurationSystem/Client/Helpers/Resources.py +11 -43
- DIRAC/ConfigurationSystem/Client/Helpers/test/Test_Helpers.py +0 -16
- DIRAC/ConfigurationSystem/Client/LocalConfiguration.py +14 -8
- DIRAC/ConfigurationSystem/Client/PathFinder.py +47 -8
- DIRAC/ConfigurationSystem/Client/SyncPlugins/CERNLDAPSyncPlugin.py +4 -1
- DIRAC/ConfigurationSystem/Client/VOMS2CSSynchronizer.py +9 -2
- DIRAC/ConfigurationSystem/Client/test/Test_PathFinder.py +41 -1
- DIRAC/ConfigurationSystem/private/RefresherBase.py +4 -2
- DIRAC/Core/DISET/ServiceReactor.py +11 -3
- DIRAC/Core/DISET/private/BaseClient.py +1 -2
- DIRAC/Core/DISET/private/Transports/M2SSLTransport.py +9 -7
- DIRAC/Core/Security/DiracX.py +12 -7
- DIRAC/Core/Security/IAMService.py +4 -3
- DIRAC/Core/Security/ProxyInfo.py +9 -5
- DIRAC/Core/Security/test/test_diracx_token_from_pem.py +161 -0
- DIRAC/Core/Tornado/Client/ClientSelector.py +4 -1
- DIRAC/Core/Tornado/Server/TornadoService.py +1 -1
- DIRAC/Core/Utilities/ClassAd/ClassAdLight.py +4 -290
- DIRAC/Core/Utilities/DErrno.py +5 -309
- DIRAC/Core/Utilities/Extensions.py +10 -1
- DIRAC/Core/Utilities/Graphs/GraphData.py +1 -1
- DIRAC/Core/Utilities/JDL.py +1 -195
- DIRAC/Core/Utilities/List.py +1 -124
- DIRAC/Core/Utilities/MySQL.py +101 -97
- DIRAC/Core/Utilities/Os.py +32 -1
- DIRAC/Core/Utilities/Platform.py +2 -107
- DIRAC/Core/Utilities/ReturnValues.py +7 -252
- DIRAC/Core/Utilities/StateMachine.py +12 -178
- DIRAC/Core/Utilities/TimeUtilities.py +10 -253
- DIRAC/Core/Utilities/test/Test_JDL.py +0 -3
- DIRAC/Core/Utilities/test/Test_Profiler.py +20 -20
- DIRAC/Core/scripts/dirac_agent.py +1 -1
- DIRAC/Core/scripts/dirac_apptainer_exec.py +16 -7
- DIRAC/Core/scripts/dirac_platform.py +1 -92
- DIRAC/DataManagementSystem/Agent/FTS3Agent.py +8 -7
- DIRAC/DataManagementSystem/Agent/RequestOperations/RemoveFile.py +7 -6
- DIRAC/DataManagementSystem/Client/FTS3Job.py +71 -34
- DIRAC/DataManagementSystem/DB/FTS3DB.py +3 -0
- DIRAC/DataManagementSystem/DB/FileCatalogComponents/DatasetManager/DatasetManager.py +1 -1
- DIRAC/DataManagementSystem/Utilities/DMSHelpers.py +6 -2
- DIRAC/DataManagementSystem/scripts/dirac_dms_create_moving_request.py +2 -0
- DIRAC/DataManagementSystem/scripts/dirac_dms_protocol_matrix.py +0 -1
- DIRAC/FrameworkSystem/Client/ComponentInstaller.py +4 -2
- DIRAC/FrameworkSystem/DB/ProxyDB.py +9 -5
- DIRAC/FrameworkSystem/Utilities/TokenManagementUtilities.py +3 -2
- DIRAC/FrameworkSystem/Utilities/diracx.py +2 -74
- DIRAC/FrameworkSystem/private/authorization/AuthServer.py +2 -2
- DIRAC/FrameworkSystem/scripts/dirac_login.py +2 -2
- DIRAC/FrameworkSystem/scripts/dirac_proxy_init.py +1 -1
- DIRAC/Interfaces/API/Dirac.py +27 -13
- DIRAC/Interfaces/API/DiracAdmin.py +42 -7
- DIRAC/Interfaces/API/Job.py +1 -0
- DIRAC/Interfaces/scripts/dirac_admin_allow_site.py +7 -1
- DIRAC/Interfaces/scripts/dirac_admin_ban_site.py +7 -1
- DIRAC/Interfaces/scripts/dirac_wms_job_parameters.py +0 -1
- DIRAC/MonitoringSystem/Client/Types/WMSHistory.py +4 -0
- DIRAC/MonitoringSystem/Client/WebAppClient.py +26 -0
- DIRAC/MonitoringSystem/ConfigTemplate.cfg +9 -0
- DIRAC/MonitoringSystem/DB/MonitoringDB.py +6 -25
- DIRAC/MonitoringSystem/Service/MonitoringHandler.py +0 -33
- DIRAC/MonitoringSystem/Service/WebAppHandler.py +599 -0
- DIRAC/MonitoringSystem/private/MainReporter.py +0 -3
- DIRAC/ProductionSystem/scripts/dirac_prod_get_trans.py +2 -3
- DIRAC/RequestManagementSystem/Agent/RequestExecutingAgent.py +8 -6
- DIRAC/RequestManagementSystem/ConfigTemplate.cfg +6 -6
- DIRAC/RequestManagementSystem/DB/test/RMSTestScenari.py +2 -0
- DIRAC/ResourceStatusSystem/Client/SiteStatus.py +4 -2
- DIRAC/ResourceStatusSystem/Command/FreeDiskSpaceCommand.py +3 -1
- DIRAC/ResourceStatusSystem/Utilities/CSHelpers.py +2 -31
- DIRAC/ResourceStatusSystem/scripts/dirac_rss_set_status.py +18 -4
- DIRAC/Resources/Catalog/RucioFileCatalogClient.py +1 -1
- DIRAC/Resources/Computing/AREXComputingElement.py +19 -3
- DIRAC/Resources/Computing/BatchSystems/Condor.py +126 -108
- DIRAC/Resources/Computing/BatchSystems/SLURM.py +5 -1
- DIRAC/Resources/Computing/BatchSystems/test/Test_SLURM.py +46 -0
- DIRAC/Resources/Computing/HTCondorCEComputingElement.py +37 -43
- DIRAC/Resources/Computing/SingularityComputingElement.py +6 -1
- DIRAC/Resources/Computing/test/Test_HTCondorCEComputingElement.py +67 -49
- DIRAC/Resources/Computing/test/Test_PoolComputingElement.py +2 -1
- DIRAC/Resources/IdProvider/CheckInIdProvider.py +13 -0
- DIRAC/Resources/IdProvider/IdProviderFactory.py +11 -3
- DIRAC/Resources/Storage/StorageBase.py +4 -2
- DIRAC/Resources/Storage/StorageElement.py +4 -4
- DIRAC/TransformationSystem/Agent/TaskManagerAgentBase.py +10 -16
- DIRAC/TransformationSystem/Agent/TransformationAgent.py +22 -1
- DIRAC/TransformationSystem/Agent/TransformationCleaningAgent.py +15 -15
- DIRAC/TransformationSystem/Client/Transformation.py +2 -1
- DIRAC/TransformationSystem/Client/TransformationClient.py +0 -7
- DIRAC/TransformationSystem/Client/Utilities.py +9 -0
- DIRAC/TransformationSystem/Service/TransformationManagerHandler.py +0 -336
- DIRAC/TransformationSystem/Utilities/ReplicationCLIParameters.py +3 -3
- DIRAC/TransformationSystem/scripts/dirac_production_runjoblocal.py +2 -4
- DIRAC/TransformationSystem/test/Test_replicationTransformation.py +5 -6
- DIRAC/Workflow/Modules/test/Test_Modules.py +5 -0
- DIRAC/WorkloadManagementSystem/Agent/JobAgent.py +1 -5
- DIRAC/WorkloadManagementSystem/Agent/JobCleaningAgent.py +11 -7
- DIRAC/WorkloadManagementSystem/Agent/PilotSyncAgent.py +4 -3
- DIRAC/WorkloadManagementSystem/Agent/PushJobAgent.py +13 -13
- DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py +10 -13
- DIRAC/WorkloadManagementSystem/Agent/StalledJobAgent.py +18 -51
- DIRAC/WorkloadManagementSystem/Agent/StatesAccountingAgent.py +41 -1
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobAgent.py +2 -0
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobCleaningAgent.py +7 -9
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PushJobAgent.py +1 -0
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_SiteDirector.py +8 -2
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_StalledJobAgent.py +4 -5
- DIRAC/WorkloadManagementSystem/Client/DownloadInputData.py +7 -5
- DIRAC/WorkloadManagementSystem/Client/JobMonitoringClient.py +10 -11
- DIRAC/WorkloadManagementSystem/Client/JobState/JobManifest.py +32 -261
- DIRAC/WorkloadManagementSystem/Client/JobStateUpdateClient.py +3 -0
- DIRAC/WorkloadManagementSystem/Client/JobStatus.py +8 -152
- DIRAC/WorkloadManagementSystem/Client/SandboxStoreClient.py +25 -38
- DIRAC/WorkloadManagementSystem/Client/WMSClient.py +2 -3
- DIRAC/WorkloadManagementSystem/Client/test/Test_Client_DownloadInputData.py +29 -0
- DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg +4 -8
- DIRAC/WorkloadManagementSystem/DB/JobDB.py +40 -69
- DIRAC/WorkloadManagementSystem/DB/JobDBUtils.py +18 -147
- DIRAC/WorkloadManagementSystem/DB/JobParametersDB.py +9 -9
- DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py +3 -2
- DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py +28 -39
- DIRAC/WorkloadManagementSystem/DB/StatusUtils.py +125 -0
- DIRAC/WorkloadManagementSystem/DB/tests/Test_JobDB.py +1 -1
- DIRAC/WorkloadManagementSystem/DB/tests/Test_StatusUtils.py +28 -0
- DIRAC/WorkloadManagementSystem/Executor/JobSanity.py +3 -3
- DIRAC/WorkloadManagementSystem/FutureClient/JobStateUpdateClient.py +2 -14
- DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapper.py +14 -9
- DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapper.py +36 -10
- DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapperTemplate.py +4 -0
- DIRAC/WorkloadManagementSystem/Service/JobManagerHandler.py +33 -154
- DIRAC/WorkloadManagementSystem/Service/JobMonitoringHandler.py +5 -323
- DIRAC/WorkloadManagementSystem/Service/JobStateUpdateHandler.py +0 -16
- DIRAC/WorkloadManagementSystem/Service/PilotManagerHandler.py +6 -102
- DIRAC/WorkloadManagementSystem/Service/SandboxStoreHandler.py +5 -51
- DIRAC/WorkloadManagementSystem/Service/WMSAdministratorHandler.py +16 -79
- DIRAC/WorkloadManagementSystem/Utilities/JobModel.py +28 -199
- DIRAC/WorkloadManagementSystem/Utilities/JobParameters.py +65 -3
- DIRAC/WorkloadManagementSystem/Utilities/JobStatusUtility.py +2 -64
- DIRAC/WorkloadManagementSystem/Utilities/ParametricJob.py +7 -171
- DIRAC/WorkloadManagementSystem/Utilities/PilotCStoJSONSynchronizer.py +73 -7
- DIRAC/WorkloadManagementSystem/Utilities/PilotWrapper.py +2 -0
- DIRAC/WorkloadManagementSystem/Utilities/RemoteRunner.py +16 -0
- DIRAC/WorkloadManagementSystem/Utilities/Utils.py +36 -1
- DIRAC/WorkloadManagementSystem/Utilities/jobAdministration.py +15 -0
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobModel.py +1 -5
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_ParametricJob.py +45 -128
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_PilotWrapper.py +16 -0
- DIRAC/__init__.py +55 -54
- {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/METADATA +6 -4
- {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/RECORD +160 -160
- {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/WHEEL +1 -1
- {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/entry_points.txt +0 -3
- DIRAC/Core/Utilities/test/Test_List.py +0 -150
- DIRAC/Core/Utilities/test/Test_Time.py +0 -88
- DIRAC/TransformationSystem/scripts/dirac_transformation_archive.py +0 -30
- DIRAC/TransformationSystem/scripts/dirac_transformation_clean.py +0 -30
- DIRAC/TransformationSystem/scripts/dirac_transformation_remove_output.py +0 -30
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobManager.py +0 -58
- {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/licenses/LICENSE +0 -0
- {dirac-9.0.0a54.dist-info → dirac-9.0.7.dist-info}/top_level.txt +0 -0
|
@@ -2,294 +2,8 @@
|
|
|
2
2
|
Condor ClassAd library.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
# Import from DIRACCommon for backward compatibility
|
|
6
|
+
from DIRACCommon.Core.Utilities.ClassAd.ClassAdLight import ClassAd
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"""ClassAd constructor from a JDL string"""
|
|
9
|
-
self.contents = {}
|
|
10
|
-
result = self.__analyse_jdl(jdl)
|
|
11
|
-
if result:
|
|
12
|
-
self.contents = result
|
|
13
|
-
|
|
14
|
-
def __analyse_jdl(self, jdl, index=0):
|
|
15
|
-
"""Analyse one [] jdl enclosure"""
|
|
16
|
-
|
|
17
|
-
jdl = jdl.strip()
|
|
18
|
-
|
|
19
|
-
# Strip all the blanks first
|
|
20
|
-
# temp = jdl.replace(' ','').replace('\n','')
|
|
21
|
-
temp = jdl
|
|
22
|
-
|
|
23
|
-
result = {}
|
|
24
|
-
|
|
25
|
-
if temp[0] != "[" or temp[-1] != "]":
|
|
26
|
-
print("Invalid JDL: it should start with [ and end with ]")
|
|
27
|
-
return result
|
|
28
|
-
|
|
29
|
-
# Parse the jdl string now
|
|
30
|
-
body = temp[1:-1]
|
|
31
|
-
index = 0
|
|
32
|
-
namemode = 1
|
|
33
|
-
valuemode = 0
|
|
34
|
-
while index < len(body):
|
|
35
|
-
if namemode:
|
|
36
|
-
ind = body.find("=", index)
|
|
37
|
-
if ind != -1:
|
|
38
|
-
name = body[index:ind]
|
|
39
|
-
index = ind + 1
|
|
40
|
-
valuemode = 1
|
|
41
|
-
namemode = 0
|
|
42
|
-
else:
|
|
43
|
-
break
|
|
44
|
-
elif valuemode:
|
|
45
|
-
ind1 = body.find("[", index)
|
|
46
|
-
ind2 = body.find(";", index)
|
|
47
|
-
if ind1 != -1 and ind1 < ind2:
|
|
48
|
-
value, newind = self.__find_subjdl(body, ind1)
|
|
49
|
-
elif ind1 == -1 and ind2 == -1:
|
|
50
|
-
value = body[index:]
|
|
51
|
-
newind = len(body)
|
|
52
|
-
else:
|
|
53
|
-
if index == ind2:
|
|
54
|
-
return {}
|
|
55
|
-
else:
|
|
56
|
-
value = body[index:ind2]
|
|
57
|
-
newind = ind2 + 1
|
|
58
|
-
|
|
59
|
-
result[name.strip()] = value.strip().replace("\n", "")
|
|
60
|
-
index = newind
|
|
61
|
-
valuemode = 0
|
|
62
|
-
namemode = 1
|
|
63
|
-
|
|
64
|
-
return result
|
|
65
|
-
|
|
66
|
-
def __find_subjdl(self, body, index):
|
|
67
|
-
"""Find a full [] enclosure starting from index"""
|
|
68
|
-
result = ""
|
|
69
|
-
if body[index] != "[":
|
|
70
|
-
return (result, 0)
|
|
71
|
-
|
|
72
|
-
depth = 0
|
|
73
|
-
ind = index
|
|
74
|
-
while depth < 10:
|
|
75
|
-
ind1 = body.find("]", ind + 1)
|
|
76
|
-
ind2 = body.find("[", ind + 1)
|
|
77
|
-
if ind2 != -1 and ind2 < ind1:
|
|
78
|
-
depth += 1
|
|
79
|
-
ind = ind2
|
|
80
|
-
else:
|
|
81
|
-
if depth > 0:
|
|
82
|
-
depth -= 1
|
|
83
|
-
ind = ind1
|
|
84
|
-
else:
|
|
85
|
-
result = body[index : ind1 + 1]
|
|
86
|
-
if body[ind1 + 1] == ";":
|
|
87
|
-
return (result, ind1 + 2)
|
|
88
|
-
return result, 0
|
|
89
|
-
|
|
90
|
-
return result, 0
|
|
91
|
-
|
|
92
|
-
def insertAttributeInt(self, name, attribute):
|
|
93
|
-
"""Insert a named integer attribute"""
|
|
94
|
-
|
|
95
|
-
self.contents[name] = str(attribute)
|
|
96
|
-
|
|
97
|
-
def insertAttributeBool(self, name, attribute):
|
|
98
|
-
"""Insert a named boolean attribute"""
|
|
99
|
-
|
|
100
|
-
if attribute:
|
|
101
|
-
self.contents[name] = "true"
|
|
102
|
-
else:
|
|
103
|
-
self.contents[name] = "false"
|
|
104
|
-
|
|
105
|
-
def insertAttributeString(self, name, attribute):
|
|
106
|
-
"""Insert a named string attribute"""
|
|
107
|
-
|
|
108
|
-
self.contents[name] = '"' + str(attribute) + '"'
|
|
109
|
-
|
|
110
|
-
def insertAttributeVectorString(self, name, attributelist):
|
|
111
|
-
"""Insert a named string list attribute"""
|
|
112
|
-
|
|
113
|
-
tmp = ['"' + x + '"' for x in attributelist]
|
|
114
|
-
tmpstr = ",".join(tmp)
|
|
115
|
-
self.contents[name] = "{" + tmpstr + "}"
|
|
116
|
-
|
|
117
|
-
def insertAttributeVectorInt(self, name, attributelist):
|
|
118
|
-
"""Insert a named string list attribute"""
|
|
119
|
-
|
|
120
|
-
tmp = [str(x) for x in attributelist]
|
|
121
|
-
tmpstr = ",".join(tmp)
|
|
122
|
-
self.contents[name] = "{" + tmpstr + "}"
|
|
123
|
-
|
|
124
|
-
def insertAttributeVectorStringList(self, name, attributelist):
|
|
125
|
-
"""Insert a named list of string lists"""
|
|
126
|
-
|
|
127
|
-
listOfLists = []
|
|
128
|
-
for stringList in attributelist:
|
|
129
|
-
# tmp = map ( lambda x : '"' + x + '"', stringList )
|
|
130
|
-
tmpstr = ",".join(stringList)
|
|
131
|
-
listOfLists.append("{" + tmpstr + "}")
|
|
132
|
-
self.contents[name] = "{" + ",".join(listOfLists) + "}"
|
|
133
|
-
|
|
134
|
-
def lookupAttribute(self, name):
|
|
135
|
-
"""Check the presence of the given attribute"""
|
|
136
|
-
|
|
137
|
-
return name in self.contents
|
|
138
|
-
|
|
139
|
-
def set_expression(self, name, attribute):
|
|
140
|
-
"""Insert a named expression attribute"""
|
|
141
|
-
|
|
142
|
-
self.contents[name] = str(attribute)
|
|
143
|
-
|
|
144
|
-
def get_expression(self, name):
|
|
145
|
-
"""Get expression corresponding to a named attribute"""
|
|
146
|
-
|
|
147
|
-
if name in self.contents:
|
|
148
|
-
if isinstance(self.contents[name], int):
|
|
149
|
-
return str(self.contents[name])
|
|
150
|
-
return self.contents[name]
|
|
151
|
-
return ""
|
|
152
|
-
|
|
153
|
-
def isAttributeList(self, name):
|
|
154
|
-
"""Check if the given attribute is of the List type"""
|
|
155
|
-
attribute = self.get_expression(name).strip()
|
|
156
|
-
return attribute.startswith("{")
|
|
157
|
-
|
|
158
|
-
def getListFromExpression(self, name):
|
|
159
|
-
"""Get a list of strings from a given expression"""
|
|
160
|
-
|
|
161
|
-
tempString = self.get_expression(name).strip()
|
|
162
|
-
listMode = False
|
|
163
|
-
if tempString.startswith("{"):
|
|
164
|
-
tempString = tempString[1:-1]
|
|
165
|
-
listMode = True
|
|
166
|
-
|
|
167
|
-
tempString = tempString.replace(" ", "").replace("\n", "")
|
|
168
|
-
if tempString.find("{") < 0:
|
|
169
|
-
if not listMode:
|
|
170
|
-
tempString = tempString.replace('"', "")
|
|
171
|
-
if not tempString:
|
|
172
|
-
return []
|
|
173
|
-
return tempString.split(",")
|
|
174
|
-
|
|
175
|
-
resultList = []
|
|
176
|
-
while tempString:
|
|
177
|
-
if tempString.find("{") == 0:
|
|
178
|
-
end = tempString.find("}")
|
|
179
|
-
resultList.append(tempString[: end + 1])
|
|
180
|
-
tempString = tempString[end + 1 :]
|
|
181
|
-
if tempString.startswith(","):
|
|
182
|
-
tempString = tempString[1:]
|
|
183
|
-
elif tempString.find('"') == 0:
|
|
184
|
-
end = tempString[1:].find('"')
|
|
185
|
-
resultList.append(tempString[1 : end + 1])
|
|
186
|
-
tempString = tempString[end + 2 :]
|
|
187
|
-
if tempString.startswith(","):
|
|
188
|
-
tempString = tempString[1:]
|
|
189
|
-
else:
|
|
190
|
-
end = tempString.find(",")
|
|
191
|
-
if end < 0:
|
|
192
|
-
resultList.append(tempString.replace('"', "").replace(" ", ""))
|
|
193
|
-
break
|
|
194
|
-
else:
|
|
195
|
-
resultList.append(tempString[:end].replace('"', "").replace(" ", ""))
|
|
196
|
-
tempString = tempString[end + 1 :]
|
|
197
|
-
|
|
198
|
-
return resultList
|
|
199
|
-
|
|
200
|
-
def getDictionaryFromSubJDL(self, name):
|
|
201
|
-
"""Get a dictionary of the JDL attributes from a subsection"""
|
|
202
|
-
|
|
203
|
-
tempList = self.get_expression(name)[1:-1]
|
|
204
|
-
resDict = {}
|
|
205
|
-
for item in tempList.split(";"):
|
|
206
|
-
if len(item.split("=")) == 2:
|
|
207
|
-
resDict[item.split("=")[0].strip()] = item.split("=")[1].strip().replace('"', "")
|
|
208
|
-
else:
|
|
209
|
-
return {}
|
|
210
|
-
|
|
211
|
-
return resDict
|
|
212
|
-
|
|
213
|
-
def deleteAttribute(self, name):
|
|
214
|
-
"""Delete a named attribute"""
|
|
215
|
-
|
|
216
|
-
if name in self.contents:
|
|
217
|
-
del self.contents[name]
|
|
218
|
-
return 1
|
|
219
|
-
return 0
|
|
220
|
-
|
|
221
|
-
def isOK(self):
|
|
222
|
-
"""Check the JDL validity - to be defined"""
|
|
223
|
-
|
|
224
|
-
if self.contents:
|
|
225
|
-
return 1
|
|
226
|
-
return 0
|
|
227
|
-
|
|
228
|
-
def asJDL(self):
|
|
229
|
-
"""Convert the JDL description into a string"""
|
|
230
|
-
|
|
231
|
-
result = []
|
|
232
|
-
for name, value in sorted(self.contents.items()):
|
|
233
|
-
if value[0:1] == "{":
|
|
234
|
-
result += [4 * " " + name + " = \n"]
|
|
235
|
-
result += [8 * " " + "{\n"]
|
|
236
|
-
strings = value[1:-1].split(",")
|
|
237
|
-
for st in strings:
|
|
238
|
-
result += [12 * " " + st.strip() + ",\n"]
|
|
239
|
-
result[-1] = result[-1][:-2]
|
|
240
|
-
result += ["\n" + 8 * " " + "};\n"]
|
|
241
|
-
elif value[0:1] == "[":
|
|
242
|
-
tempad = ClassAd(value)
|
|
243
|
-
tempjdl = tempad.asJDL() + ";"
|
|
244
|
-
lines = tempjdl.split("\n")
|
|
245
|
-
result += [4 * " " + name + " = \n"]
|
|
246
|
-
for line in lines:
|
|
247
|
-
result += [8 * " " + line + "\n"]
|
|
248
|
-
|
|
249
|
-
else:
|
|
250
|
-
result += [4 * " " + name + " = " + str(value) + ";\n"]
|
|
251
|
-
if result:
|
|
252
|
-
result[-1] = result[-1][:-1]
|
|
253
|
-
return "[ \n" + "".join(result) + "\n]"
|
|
254
|
-
|
|
255
|
-
def getAttributeString(self, name):
|
|
256
|
-
"""Get String type attribute value"""
|
|
257
|
-
value = ""
|
|
258
|
-
if self.lookupAttribute(name):
|
|
259
|
-
value = self.get_expression(name).replace('"', "")
|
|
260
|
-
return value
|
|
261
|
-
|
|
262
|
-
def getAttributeInt(self, name):
|
|
263
|
-
"""Get Integer type attribute value"""
|
|
264
|
-
value = None
|
|
265
|
-
if self.lookupAttribute(name):
|
|
266
|
-
try:
|
|
267
|
-
value = int(self.get_expression(name).replace('"', ""))
|
|
268
|
-
except Exception:
|
|
269
|
-
value = None
|
|
270
|
-
return value
|
|
271
|
-
|
|
272
|
-
def getAttributeBool(self, name):
|
|
273
|
-
"""Get Boolean type attribute value"""
|
|
274
|
-
if not self.lookupAttribute(name):
|
|
275
|
-
return False
|
|
276
|
-
|
|
277
|
-
value = self.get_expression(name).replace('"', "")
|
|
278
|
-
return value.lower() == "true"
|
|
279
|
-
|
|
280
|
-
def getAttributeFloat(self, name):
|
|
281
|
-
"""Get Float type attribute value"""
|
|
282
|
-
value = None
|
|
283
|
-
if self.lookupAttribute(name):
|
|
284
|
-
try:
|
|
285
|
-
value = float(self.get_expression(name).replace('"', ""))
|
|
286
|
-
except Exception:
|
|
287
|
-
value = None
|
|
288
|
-
return value
|
|
289
|
-
|
|
290
|
-
def getAttributes(self) -> list[str]:
|
|
291
|
-
"""Get the list of all the attribute names
|
|
292
|
-
|
|
293
|
-
:return: list of names as strings
|
|
294
|
-
"""
|
|
295
|
-
return list(self.contents)
|
|
8
|
+
# Re-export for backward compatibility
|
|
9
|
+
__all__ = ["ClassAd"]
|
DIRAC/Core/Utilities/DErrno.py
CHANGED
|
@@ -37,320 +37,16 @@
|
|
|
37
37
|
DErrno.ERRX : ['An error message for ERRX that is specific to LHCb']}
|
|
38
38
|
|
|
39
39
|
"""
|
|
40
|
-
import os
|
|
41
40
|
import importlib
|
|
42
41
|
import sys
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# To avoid conflict, the error numbers should be greater than 1000
|
|
47
|
-
# We decided to group the by range of 100 per system
|
|
48
|
-
|
|
49
|
-
# 1000: Generic
|
|
50
|
-
# 1100: Core
|
|
51
|
-
# 1200: Framework
|
|
52
|
-
# 1300: Interfaces
|
|
53
|
-
# 1400: Config
|
|
54
|
-
# 1500: WMS + Workflow
|
|
55
|
-
# 1600: DMS + StorageManagement
|
|
56
|
-
# 1700: RMS
|
|
57
|
-
# 1800: Accounting + Monitoring
|
|
58
|
-
# 1900: TS + Production
|
|
59
|
-
# 2000: Resources + RSS
|
|
60
|
-
|
|
61
|
-
# ## Generic (10XX)
|
|
62
|
-
# Python related: 0X
|
|
63
|
-
ETYPE = 1000
|
|
64
|
-
EIMPERR = 1001
|
|
65
|
-
ENOMETH = 1002
|
|
66
|
-
ECONF = 1003
|
|
67
|
-
EVALUE = 1004
|
|
68
|
-
EEEXCEPTION = 1005
|
|
69
|
-
# Files manipulation: 1X
|
|
70
|
-
ECTMPF = 1010
|
|
71
|
-
EOF = 1011
|
|
72
|
-
ERF = 1012
|
|
73
|
-
EWF = 1013
|
|
74
|
-
ESPF = 1014
|
|
75
|
-
|
|
76
|
-
# ## Core (11XX)
|
|
77
|
-
# Certificates and Proxy: 0X
|
|
78
|
-
EX509 = 1100
|
|
79
|
-
EPROXYFIND = 1101
|
|
80
|
-
EPROXYREAD = 1102
|
|
81
|
-
ECERTFIND = 1103
|
|
82
|
-
ECERTREAD = 1104
|
|
83
|
-
ENOCERT = 1105
|
|
84
|
-
ENOCHAIN = 1106
|
|
85
|
-
ENOPKEY = 1107
|
|
86
|
-
ENOGROUP = 1108
|
|
87
|
-
# DISET: 1X
|
|
88
|
-
EDISET = 1110
|
|
89
|
-
ENOAUTH = 1111
|
|
90
|
-
# 3rd party security: 2X
|
|
91
|
-
E3RDPARTY = 1120
|
|
92
|
-
EVOMS = 1121
|
|
93
|
-
# Databases : 3X
|
|
94
|
-
EDB = 1130
|
|
95
|
-
EMYSQL = 1131
|
|
96
|
-
ESQLA = 1132
|
|
97
|
-
# Message Queues: 4X
|
|
98
|
-
EMQUKN = 1140
|
|
99
|
-
EMQNOM = 1141
|
|
100
|
-
EMQCONN = 1142
|
|
101
|
-
# OpenSearch
|
|
102
|
-
EELNOFOUND = 1146
|
|
103
|
-
# Tokens
|
|
104
|
-
EATOKENFIND = 1150
|
|
105
|
-
EATOKENREAD = 1151
|
|
106
|
-
ETOKENTYPE = 1152
|
|
107
|
-
|
|
108
|
-
# config
|
|
109
|
-
ESECTION = 1400
|
|
110
|
-
|
|
111
|
-
# processes
|
|
112
|
-
EEZOMBIE = 1147
|
|
113
|
-
EENOPID = 1148
|
|
114
|
-
|
|
115
|
-
# ## WMS/Workflow
|
|
116
|
-
EWMSUKN = 1500
|
|
117
|
-
EWMSJDL = 1501
|
|
118
|
-
EWMSRESC = 1502
|
|
119
|
-
EWMSSUBM = 1503
|
|
120
|
-
EWMSJMAN = 1504
|
|
121
|
-
EWMSSTATUS = 1505
|
|
122
|
-
EWMSNOMATCH = 1510
|
|
123
|
-
EWMSPLTVER = 1511
|
|
124
|
-
EWMSNOPILOT = 1550
|
|
125
|
-
|
|
126
|
-
# ## DMS/StorageManagement (16XX)
|
|
127
|
-
EFILESIZE = 1601
|
|
128
|
-
EGFAL = 1602
|
|
129
|
-
EBADCKS = 1603
|
|
130
|
-
EFCERR = 1604
|
|
131
|
-
|
|
132
|
-
# ## RMS (17XX)
|
|
133
|
-
ERMSUKN = 1700
|
|
134
|
-
|
|
135
|
-
# ## TS (19XX)
|
|
136
|
-
ETSUKN = 1900
|
|
137
|
-
ETSDATA = 1901
|
|
138
|
-
|
|
139
|
-
# ## Resources and RSS (20XX)
|
|
140
|
-
ERESGEN = 2000
|
|
141
|
-
ERESUNA = 2001
|
|
142
|
-
ERESUNK = 2002
|
|
143
|
-
|
|
144
|
-
# This translates the integer number into the name of the variable
|
|
145
|
-
dErrorCode = {
|
|
146
|
-
# ## Generic (10XX)
|
|
147
|
-
# 100X: Python related
|
|
148
|
-
1000: "ETYPE",
|
|
149
|
-
1001: "EIMPERR",
|
|
150
|
-
1002: "ENOMETH",
|
|
151
|
-
1003: "ECONF",
|
|
152
|
-
1004: "EVALUE",
|
|
153
|
-
1005: "EEEXCEPTION",
|
|
154
|
-
# 101X: Files manipulation
|
|
155
|
-
1010: "ECTMPF",
|
|
156
|
-
1011: "EOF",
|
|
157
|
-
1012: "ERF",
|
|
158
|
-
1013: "EWF",
|
|
159
|
-
1014: "ESPF",
|
|
160
|
-
# ## Core
|
|
161
|
-
# 110X: Certificates and Proxy
|
|
162
|
-
1100: "EX509",
|
|
163
|
-
1101: "EPROXYFIND",
|
|
164
|
-
1102: "EPROXYREAD",
|
|
165
|
-
1103: "ECERTFIND",
|
|
166
|
-
1104: "ECERTREAD",
|
|
167
|
-
1105: "ENOCERT",
|
|
168
|
-
1106: "ENOCHAIN",
|
|
169
|
-
1107: "ENOPKEY",
|
|
170
|
-
1108: "ENOGROUP",
|
|
171
|
-
# 111X: DISET
|
|
172
|
-
1110: "EDISET",
|
|
173
|
-
1111: "ENOAUTH",
|
|
174
|
-
# 112X: 3rd party security
|
|
175
|
-
1120: "E3RDPARTY",
|
|
176
|
-
1121: "EVOMS",
|
|
177
|
-
# 113X: Databases
|
|
178
|
-
1130: "EDB",
|
|
179
|
-
1131: "EMYSQL",
|
|
180
|
-
1132: "ESQLA",
|
|
181
|
-
# 114X: Message Queues
|
|
182
|
-
1140: "EMQUKN",
|
|
183
|
-
1141: "EMQNOM",
|
|
184
|
-
1142: "EMQCONN",
|
|
185
|
-
# OpenSearch
|
|
186
|
-
1146: "EELNOFOUND",
|
|
187
|
-
# 115X: Tokens
|
|
188
|
-
1150: "EATOKENFIND",
|
|
189
|
-
1151: "EATOKENREAD",
|
|
190
|
-
1152: "ETOKENTYPE",
|
|
191
|
-
# Config
|
|
192
|
-
1400: "ESECTION",
|
|
193
|
-
# Processes
|
|
194
|
-
1147: "EEZOMBIE",
|
|
195
|
-
1148: "EENOPID",
|
|
196
|
-
# WMS/Workflow
|
|
197
|
-
1500: "EWMSUKN",
|
|
198
|
-
1501: "EWMSJDL",
|
|
199
|
-
1502: "EWMSRESC",
|
|
200
|
-
1503: "EWMSSUBM",
|
|
201
|
-
1504: "EWMSJMAN",
|
|
202
|
-
1505: "EWMSSTATUS",
|
|
203
|
-
1510: "EWMSNOMATCH",
|
|
204
|
-
1511: "EWMSPLTVER",
|
|
205
|
-
1550: "EWMSNOPILOT",
|
|
206
|
-
# DMS/StorageManagement
|
|
207
|
-
1601: "EFILESIZE",
|
|
208
|
-
1602: "EGFAL",
|
|
209
|
-
1603: "EBADCKS",
|
|
210
|
-
1604: "EFCERR",
|
|
211
|
-
# RMS
|
|
212
|
-
1700: "ERMSUKN",
|
|
213
|
-
# Resources and RSS
|
|
214
|
-
2000: "ERESGEN",
|
|
215
|
-
2001: "ERESUNA",
|
|
216
|
-
2002: "ERESUNK",
|
|
217
|
-
# TS
|
|
218
|
-
1900: "ETSUKN",
|
|
219
|
-
1901: "ETSDATA",
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
dStrError = { # Generic (10XX)
|
|
224
|
-
# 100X: Python related
|
|
225
|
-
ETYPE: "Object Type Error",
|
|
226
|
-
EIMPERR: "Failed to import library",
|
|
227
|
-
ENOMETH: "No such method or function",
|
|
228
|
-
ECONF: "Configuration error",
|
|
229
|
-
EVALUE: "Wrong value passed",
|
|
230
|
-
EEEXCEPTION: "runtime general exception",
|
|
231
|
-
# 101X: Files manipulation
|
|
232
|
-
ECTMPF: "Failed to create temporary file",
|
|
233
|
-
EOF: "Cannot open file",
|
|
234
|
-
ERF: "Cannot read from file",
|
|
235
|
-
EWF: "Cannot write to file",
|
|
236
|
-
ESPF: "Cannot set permissions to file",
|
|
237
|
-
# ## Core
|
|
238
|
-
# 110X: Certificates and Proxy
|
|
239
|
-
EX509: "Generic Error with X509",
|
|
240
|
-
EPROXYFIND: "Can't find proxy",
|
|
241
|
-
EPROXYREAD: "Can't read proxy",
|
|
242
|
-
ECERTFIND: "Can't find certificate",
|
|
243
|
-
ECERTREAD: "Can't read certificate",
|
|
244
|
-
ENOCERT: "No certificate loaded",
|
|
245
|
-
ENOCHAIN: "No chain loaded",
|
|
246
|
-
ENOPKEY: "No private key loaded",
|
|
247
|
-
ENOGROUP: "No DIRAC group",
|
|
248
|
-
# 111X: DISET
|
|
249
|
-
EDISET: "DISET Error",
|
|
250
|
-
ENOAUTH: "Unauthorized query",
|
|
251
|
-
# 112X: 3rd party security
|
|
252
|
-
E3RDPARTY: "3rd party security service error",
|
|
253
|
-
EVOMS: "VOMS Error",
|
|
254
|
-
# 113X: Databases
|
|
255
|
-
EDB: "Database Error",
|
|
256
|
-
EMYSQL: "MySQL Error",
|
|
257
|
-
ESQLA: "SQLAlchemy Error",
|
|
258
|
-
# 114X: Message Queues
|
|
259
|
-
EMQUKN: "Unknown MQ Error",
|
|
260
|
-
EMQNOM: "No messages",
|
|
261
|
-
EMQCONN: "MQ connection failure",
|
|
262
|
-
# 114X OpenSearch
|
|
263
|
-
EELNOFOUND: "Index not found",
|
|
264
|
-
# 115X: Tokens
|
|
265
|
-
EATOKENFIND: "Can't find a bearer access token.",
|
|
266
|
-
EATOKENREAD: "Can't read a bearer access token.",
|
|
267
|
-
ETOKENTYPE: "Unsupported access token type.",
|
|
268
|
-
# Config
|
|
269
|
-
ESECTION: "Section is not found",
|
|
270
|
-
# processes
|
|
271
|
-
EEZOMBIE: "Zombie process",
|
|
272
|
-
EENOPID: "No PID of process",
|
|
273
|
-
# WMS/Workflow
|
|
274
|
-
EWMSUKN: "Unknown WMS error",
|
|
275
|
-
EWMSJDL: "Invalid job description",
|
|
276
|
-
EWMSRESC: "Job to reschedule",
|
|
277
|
-
EWMSSUBM: "Job submission error",
|
|
278
|
-
EWMSJMAN: "Job management error",
|
|
279
|
-
EWMSSTATUS: "Job status error",
|
|
280
|
-
EWMSNOPILOT: "No pilots found",
|
|
281
|
-
EWMSPLTVER: "Pilot version does not match",
|
|
282
|
-
EWMSNOMATCH: "No match found",
|
|
283
|
-
# DMS/StorageManagement
|
|
284
|
-
EFILESIZE: "Bad file size",
|
|
285
|
-
EGFAL: "Error with the gfal call",
|
|
286
|
-
EBADCKS: "Bad checksum",
|
|
287
|
-
EFCERR: "FileCatalog error",
|
|
288
|
-
# RMS
|
|
289
|
-
ERMSUKN: "Unknown RMS error",
|
|
290
|
-
# Resources and RSS
|
|
291
|
-
ERESGEN: "Unknown Resource Failure",
|
|
292
|
-
ERESUNA: "Resource not available",
|
|
293
|
-
ERESUNK: "Unknown Resource",
|
|
294
|
-
# TS
|
|
295
|
-
ETSUKN: "Unknown Transformation System Error",
|
|
296
|
-
ETSDATA: "Invalid Input Data definition",
|
|
297
|
-
}
|
|
43
|
+
# Import all the stateless parts from DIRACCommon
|
|
44
|
+
from DIRACCommon.Core.Utilities.DErrno import * # noqa: F401, F403
|
|
298
45
|
|
|
46
|
+
from DIRAC.Core.Utilities.Extensions import extensionsByPriority
|
|
299
47
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
It completes it with the DIRAC specific errors.
|
|
303
|
-
"""
|
|
304
|
-
|
|
305
|
-
if code == 0:
|
|
306
|
-
return "Undefined error"
|
|
307
|
-
|
|
308
|
-
errMsg = f"Unknown error {code}"
|
|
309
|
-
|
|
310
|
-
try:
|
|
311
|
-
errMsg = dStrError[code]
|
|
312
|
-
except KeyError:
|
|
313
|
-
# It is not a DIRAC specific error, try the os one
|
|
314
|
-
try:
|
|
315
|
-
errMsg = os.strerror(code)
|
|
316
|
-
# On some system, os.strerror raises an exception with unknown code,
|
|
317
|
-
# on others, it returns a message...
|
|
318
|
-
except ValueError:
|
|
319
|
-
pass
|
|
320
|
-
|
|
321
|
-
return errMsg
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
def cmpError(inErr, candidate):
|
|
325
|
-
"""This function compares an error (in its old form (a string or dictionary) or in its int form
|
|
326
|
-
with a candidate error code.
|
|
327
|
-
|
|
328
|
-
:param inErr: a string, an integer, a S_ERROR dictionary
|
|
329
|
-
:type inErr: str or int or S_ERROR
|
|
330
|
-
:param int candidate: error code to compare with
|
|
331
|
-
|
|
332
|
-
:return: True or False
|
|
333
|
-
|
|
334
|
-
If an S_ERROR instance is passed, we compare the code with S_ERROR['Errno']
|
|
335
|
-
If it is a Integer, we do a direct comparison
|
|
336
|
-
If it is a String, we use strerror to check the error string
|
|
337
|
-
"""
|
|
338
|
-
|
|
339
|
-
if isinstance(inErr, str): # old style
|
|
340
|
-
# Compare error message strings
|
|
341
|
-
errMsg = strerror(candidate)
|
|
342
|
-
return errMsg in inErr
|
|
343
|
-
elif isinstance(inErr, dict): # if the S_ERROR structure is given
|
|
344
|
-
# Check if Errno defined in the dict
|
|
345
|
-
errorNumber = inErr.get("Errno")
|
|
346
|
-
if errorNumber:
|
|
347
|
-
return errorNumber == candidate
|
|
348
|
-
errMsg = strerror(candidate)
|
|
349
|
-
return errMsg in inErr.get("Message", "")
|
|
350
|
-
elif isinstance(inErr, int):
|
|
351
|
-
return inErr == candidate
|
|
352
|
-
else:
|
|
353
|
-
raise TypeError(f"Unknown input error type {type(inErr)}")
|
|
48
|
+
# compatErrorString is used by the extension mechanism but not in DIRACCommon
|
|
49
|
+
compatErrorString = {}
|
|
354
50
|
|
|
355
51
|
|
|
356
52
|
def includeExtensionErrors():
|
|
@@ -73,6 +73,15 @@ def findServices(modules):
|
|
|
73
73
|
return findModules(modules, "Service", "*Handler")
|
|
74
74
|
|
|
75
75
|
|
|
76
|
+
def findFutureServices(modules):
|
|
77
|
+
"""Find the legacy adapted services for one or more DIRAC extension(s)
|
|
78
|
+
|
|
79
|
+
:param list/str/module module: One or more Python modules or Python module names
|
|
80
|
+
:returns: list of tuples of the form (SystemName, ServiceName)
|
|
81
|
+
"""
|
|
82
|
+
return findModules(modules, "FutureClient")
|
|
83
|
+
|
|
84
|
+
|
|
76
85
|
@iterateThenSort
|
|
77
86
|
def findDatabases(module):
|
|
78
87
|
"""Find the DB SQL schema defintions for one or more DIRAC extension(s)
|
|
@@ -182,7 +191,7 @@ def parseArgs():
|
|
|
182
191
|
parser = argparse.ArgumentParser()
|
|
183
192
|
subparsers = parser.add_subparsers(required=True, dest="function")
|
|
184
193
|
defaultExtensions = extensionsByPriority()
|
|
185
|
-
for func in [findSystems, findAgents, findExecutors, findServices, findDatabases]:
|
|
194
|
+
for func in [findSystems, findAgents, findExecutors, findServices, findDatabases, findFutureServices]:
|
|
186
195
|
subparser = subparsers.add_parser(func.__name__)
|
|
187
196
|
subparser.add_argument("--extensions", nargs="+", default=defaultExtensions)
|
|
188
197
|
subparser.set_defaults(func=func)
|
|
@@ -411,7 +411,7 @@ class PlotData:
|
|
|
411
411
|
self.num_keys.append(next)
|
|
412
412
|
next += 1
|
|
413
413
|
elif self.key_type == "time":
|
|
414
|
-
self.num_keys = [date2num(datetime.datetime.
|
|
414
|
+
self.num_keys = [date2num(datetime.datetime.utcfromtimestamp(to_timestamp(key))) for key in self.keys]
|
|
415
415
|
elif self.key_type == "numeric":
|
|
416
416
|
self.num_keys = [float(key) for key in self.keys]
|
|
417
417
|
|