DIRAC 9.0.0a42__py3-none-any.whl → 9.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- DIRAC/AccountingSystem/Client/AccountingCLI.py +0 -140
- DIRAC/AccountingSystem/Client/DataStoreClient.py +0 -13
- DIRAC/AccountingSystem/Client/Types/BaseAccountingType.py +0 -7
- DIRAC/AccountingSystem/ConfigTemplate.cfg +0 -5
- DIRAC/AccountingSystem/Service/DataStoreHandler.py +0 -72
- DIRAC/ConfigurationSystem/Client/Helpers/CSGlobals.py +0 -9
- DIRAC/ConfigurationSystem/Client/Helpers/Registry.py +38 -26
- DIRAC/ConfigurationSystem/Client/Helpers/Resources.py +11 -43
- DIRAC/ConfigurationSystem/Client/Helpers/test/Test_Helpers.py +0 -16
- DIRAC/ConfigurationSystem/Client/LocalConfiguration.py +14 -8
- DIRAC/ConfigurationSystem/Client/PathFinder.py +47 -8
- DIRAC/ConfigurationSystem/Client/SyncPlugins/CERNLDAPSyncPlugin.py +4 -1
- DIRAC/ConfigurationSystem/Client/VOMS2CSSynchronizer.py +32 -19
- DIRAC/ConfigurationSystem/Client/test/Test_PathFinder.py +41 -1
- DIRAC/ConfigurationSystem/private/RefresherBase.py +4 -2
- DIRAC/Core/Base/API.py +4 -7
- DIRAC/Core/Base/SQLAlchemyDB.py +1 -0
- DIRAC/Core/DISET/ServiceReactor.py +11 -3
- DIRAC/Core/DISET/private/BaseClient.py +1 -2
- DIRAC/Core/DISET/private/Transports/M2SSLTransport.py +9 -7
- DIRAC/Core/DISET/private/Transports/SSL/M2Utils.py +3 -1
- DIRAC/Core/LCG/GOCDBClient.py +5 -7
- DIRAC/Core/Security/DiracX.py +31 -17
- DIRAC/Core/Security/IAMService.py +5 -10
- DIRAC/Core/Security/Locations.py +27 -18
- DIRAC/Core/Security/ProxyInfo.py +9 -5
- DIRAC/Core/Security/VOMSService.py +2 -4
- DIRAC/Core/Security/m2crypto/X509Certificate.py +4 -6
- DIRAC/Core/Security/m2crypto/asn1_utils.py +17 -5
- DIRAC/Core/Security/test/test_diracx_token_from_pem.py +161 -0
- DIRAC/Core/Tornado/Client/ClientSelector.py +4 -1
- DIRAC/Core/Tornado/Server/TornadoService.py +1 -1
- DIRAC/Core/Utilities/CGroups2.py +328 -0
- DIRAC/Core/Utilities/ClassAd/ClassAdLight.py +4 -290
- DIRAC/Core/Utilities/DErrno.py +5 -309
- DIRAC/Core/Utilities/Extensions.py +10 -1
- DIRAC/Core/Utilities/File.py +1 -1
- DIRAC/Core/Utilities/Graphs/GraphData.py +1 -1
- DIRAC/Core/Utilities/Graphs/GraphUtilities.py +6 -1
- DIRAC/Core/Utilities/JDL.py +1 -195
- DIRAC/Core/Utilities/List.py +1 -124
- DIRAC/Core/Utilities/MySQL.py +103 -99
- DIRAC/Core/Utilities/Os.py +32 -1
- DIRAC/Core/Utilities/Platform.py +2 -107
- DIRAC/Core/Utilities/Proxy.py +0 -4
- DIRAC/Core/Utilities/ReturnValues.py +7 -252
- DIRAC/Core/Utilities/StateMachine.py +12 -178
- DIRAC/Core/Utilities/Subprocess.py +35 -14
- DIRAC/Core/Utilities/TimeUtilities.py +10 -253
- DIRAC/Core/Utilities/test/Test_JDL.py +0 -3
- DIRAC/Core/Utilities/test/Test_Profiler.py +20 -20
- DIRAC/Core/scripts/dirac_agent.py +1 -1
- DIRAC/Core/scripts/dirac_apptainer_exec.py +72 -46
- DIRAC/Core/scripts/dirac_configure.py +1 -3
- DIRAC/Core/scripts/dirac_install_db.py +24 -6
- DIRAC/Core/scripts/dirac_platform.py +1 -92
- DIRAC/DataManagementSystem/Agent/FTS3Agent.py +8 -7
- DIRAC/DataManagementSystem/Agent/RequestOperations/RemoveFile.py +7 -6
- DIRAC/DataManagementSystem/Client/FTS3Job.py +71 -34
- DIRAC/DataManagementSystem/DB/FTS3DB.py +7 -3
- DIRAC/DataManagementSystem/DB/FileCatalogComponents/DatasetManager/DatasetManager.py +1 -1
- DIRAC/DataManagementSystem/DB/FileCatalogDB.sql +9 -9
- DIRAC/DataManagementSystem/DB/FileCatalogWithFkAndPsDB.sql +9 -9
- DIRAC/DataManagementSystem/Utilities/DMSHelpers.py +6 -2
- DIRAC/DataManagementSystem/scripts/dirac_admin_allow_se.py +13 -8
- DIRAC/DataManagementSystem/scripts/dirac_admin_ban_se.py +13 -8
- DIRAC/DataManagementSystem/scripts/dirac_dms_create_moving_request.py +2 -0
- DIRAC/DataManagementSystem/scripts/dirac_dms_protocol_matrix.py +0 -1
- DIRAC/FrameworkSystem/Client/BundleDeliveryClient.py +2 -7
- DIRAC/FrameworkSystem/Client/ComponentInstaller.py +9 -4
- DIRAC/FrameworkSystem/Client/ProxyManagerClient.py +5 -2
- DIRAC/FrameworkSystem/Client/SystemAdministratorClientCLI.py +11 -6
- DIRAC/FrameworkSystem/ConfigTemplate.cfg +2 -0
- DIRAC/FrameworkSystem/DB/AuthDB.py +3 -3
- DIRAC/FrameworkSystem/DB/InstalledComponentsDB.py +4 -4
- DIRAC/FrameworkSystem/DB/ProxyDB.py +11 -3
- DIRAC/FrameworkSystem/DB/TokenDB.py +1 -1
- DIRAC/FrameworkSystem/Service/ProxyManagerHandler.py +8 -6
- DIRAC/FrameworkSystem/Utilities/MonitoringUtilities.py +2 -19
- DIRAC/FrameworkSystem/Utilities/TokenManagementUtilities.py +3 -2
- DIRAC/FrameworkSystem/Utilities/diracx.py +36 -14
- DIRAC/FrameworkSystem/private/authorization/AuthServer.py +2 -2
- DIRAC/FrameworkSystem/scripts/dirac_admin_update_pilot.py +18 -11
- DIRAC/FrameworkSystem/scripts/dirac_login.py +2 -2
- DIRAC/FrameworkSystem/scripts/dirac_proxy_init.py +7 -8
- DIRAC/Interfaces/API/Dirac.py +27 -15
- DIRAC/Interfaces/API/DiracAdmin.py +45 -17
- DIRAC/Interfaces/API/Job.py +9 -13
- DIRAC/Interfaces/scripts/dirac_admin_allow_site.py +12 -18
- DIRAC/Interfaces/scripts/dirac_admin_ban_site.py +12 -10
- DIRAC/Interfaces/scripts/dirac_admin_get_site_mask.py +4 -13
- DIRAC/Interfaces/scripts/dirac_admin_reset_job.py +3 -6
- DIRAC/Interfaces/scripts/dirac_wms_job_parameters.py +0 -1
- DIRAC/MonitoringSystem/Client/Types/WMSHistory.py +4 -0
- DIRAC/MonitoringSystem/Client/WebAppClient.py +26 -0
- DIRAC/MonitoringSystem/ConfigTemplate.cfg +9 -0
- DIRAC/MonitoringSystem/DB/MonitoringDB.py +6 -25
- DIRAC/MonitoringSystem/Service/MonitoringHandler.py +0 -33
- DIRAC/MonitoringSystem/Service/WebAppHandler.py +599 -0
- DIRAC/MonitoringSystem/private/MainReporter.py +0 -3
- DIRAC/ProductionSystem/DB/ProductionDB.sql +4 -4
- DIRAC/ProductionSystem/scripts/dirac_prod_get.py +2 -2
- DIRAC/ProductionSystem/scripts/dirac_prod_get_all.py +2 -2
- DIRAC/ProductionSystem/scripts/dirac_prod_get_trans.py +2 -3
- DIRAC/RequestManagementSystem/Agent/RequestExecutingAgent.py +8 -6
- DIRAC/RequestManagementSystem/Agent/RequestOperations/ForwardDISET.py +2 -14
- DIRAC/RequestManagementSystem/Client/ReqClient.py +66 -13
- DIRAC/RequestManagementSystem/ConfigTemplate.cfg +6 -6
- DIRAC/RequestManagementSystem/DB/RequestDB.py +10 -5
- DIRAC/RequestManagementSystem/DB/test/RMSTestScenari.py +2 -0
- DIRAC/RequestManagementSystem/private/RequestValidator.py +40 -46
- DIRAC/ResourceStatusSystem/Client/SiteStatus.py +4 -2
- DIRAC/ResourceStatusSystem/Command/FreeDiskSpaceCommand.py +3 -1
- DIRAC/ResourceStatusSystem/DB/ResourceManagementDB.py +8 -8
- DIRAC/ResourceStatusSystem/DB/ResourceStatusDB.py +2 -2
- DIRAC/ResourceStatusSystem/Utilities/CSHelpers.py +2 -31
- DIRAC/ResourceStatusSystem/scripts/dirac_rss_set_status.py +30 -12
- DIRAC/Resources/Catalog/RucioFileCatalogClient.py +195 -1
- DIRAC/Resources/Catalog/test/Test_RucioFileCatalogClient.py +181 -0
- DIRAC/Resources/Computing/AREXComputingElement.py +25 -8
- DIRAC/Resources/Computing/BatchSystems/Condor.py +126 -108
- DIRAC/Resources/Computing/BatchSystems/SLURM.py +5 -1
- DIRAC/Resources/Computing/BatchSystems/test/Test_SLURM.py +46 -0
- DIRAC/Resources/Computing/ComputingElement.py +1 -1
- DIRAC/Resources/Computing/HTCondorCEComputingElement.py +44 -44
- DIRAC/Resources/Computing/InProcessComputingElement.py +4 -2
- DIRAC/Resources/Computing/LocalComputingElement.py +1 -18
- DIRAC/Resources/Computing/SSHBatchComputingElement.py +1 -17
- DIRAC/Resources/Computing/SSHComputingElement.py +1 -18
- DIRAC/Resources/Computing/SingularityComputingElement.py +19 -5
- DIRAC/Resources/Computing/test/Test_HTCondorCEComputingElement.py +67 -49
- DIRAC/Resources/Computing/test/Test_PoolComputingElement.py +2 -1
- DIRAC/Resources/IdProvider/CheckInIdProvider.py +13 -0
- DIRAC/Resources/IdProvider/IdProviderFactory.py +11 -3
- DIRAC/Resources/MessageQueue/StompMQConnector.py +1 -1
- DIRAC/Resources/Storage/GFAL2_StorageBase.py +24 -15
- DIRAC/Resources/Storage/OccupancyPlugins/WLCGAccountingHTTPJson.py +1 -3
- DIRAC/Resources/Storage/StorageBase.py +4 -2
- DIRAC/Resources/Storage/StorageElement.py +6 -7
- DIRAC/StorageManagementSystem/DB/StorageManagementDB.sql +2 -2
- DIRAC/TransformationSystem/Agent/TaskManagerAgentBase.py +10 -16
- DIRAC/TransformationSystem/Agent/TransformationAgent.py +22 -1
- DIRAC/TransformationSystem/Agent/TransformationCleaningAgent.py +16 -16
- DIRAC/TransformationSystem/Client/TaskManager.py +2 -4
- DIRAC/TransformationSystem/Client/Transformation.py +6 -7
- DIRAC/TransformationSystem/Client/TransformationClient.py +21 -11
- DIRAC/TransformationSystem/Client/Utilities.py +9 -0
- DIRAC/TransformationSystem/DB/TransformationDB.py +11 -14
- DIRAC/TransformationSystem/DB/TransformationDB.sql +9 -9
- DIRAC/TransformationSystem/Service/TransformationManagerHandler.py +0 -333
- DIRAC/TransformationSystem/Utilities/ReplicationCLIParameters.py +3 -3
- DIRAC/TransformationSystem/Utilities/TransformationInfo.py +7 -5
- DIRAC/TransformationSystem/scripts/dirac_production_runjoblocal.py +2 -4
- DIRAC/TransformationSystem/test/Test_TransformationInfo.py +22 -15
- DIRAC/TransformationSystem/test/Test_replicationTransformation.py +5 -6
- DIRAC/Workflow/Modules/test/Test_Modules.py +5 -0
- DIRAC/WorkloadManagementSystem/Agent/JobAgent.py +38 -26
- DIRAC/WorkloadManagementSystem/Agent/JobCleaningAgent.py +12 -8
- DIRAC/WorkloadManagementSystem/Agent/PilotSyncAgent.py +4 -3
- DIRAC/WorkloadManagementSystem/Agent/PushJobAgent.py +13 -13
- DIRAC/WorkloadManagementSystem/Agent/SiteDirector.py +18 -14
- DIRAC/WorkloadManagementSystem/Agent/StalledJobAgent.py +18 -51
- DIRAC/WorkloadManagementSystem/Agent/StatesAccountingAgent.py +41 -1
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobAgent.py +45 -4
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_JobCleaningAgent.py +7 -9
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_PushJobAgent.py +1 -0
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_SiteDirector.py +9 -2
- DIRAC/WorkloadManagementSystem/Agent/test/Test_Agent_StalledJobAgent.py +4 -5
- DIRAC/WorkloadManagementSystem/Client/DownloadInputData.py +9 -9
- DIRAC/WorkloadManagementSystem/Client/InputDataResolution.py +6 -6
- DIRAC/WorkloadManagementSystem/Client/JobMonitoringClient.py +10 -11
- DIRAC/WorkloadManagementSystem/Client/JobReport.py +1 -1
- DIRAC/WorkloadManagementSystem/Client/JobState/CachedJobState.py +3 -0
- DIRAC/WorkloadManagementSystem/Client/JobState/JobManifest.py +32 -261
- DIRAC/WorkloadManagementSystem/Client/JobState/JobState.py +6 -0
- DIRAC/WorkloadManagementSystem/Client/JobStateUpdateClient.py +3 -0
- DIRAC/WorkloadManagementSystem/Client/JobStatus.py +8 -152
- DIRAC/WorkloadManagementSystem/Client/PoolXMLSlice.py +12 -19
- DIRAC/WorkloadManagementSystem/Client/SandboxStoreClient.py +25 -38
- DIRAC/WorkloadManagementSystem/Client/WMSClient.py +2 -3
- DIRAC/WorkloadManagementSystem/Client/test/Test_Client_DownloadInputData.py +29 -0
- DIRAC/WorkloadManagementSystem/ConfigTemplate.cfg +4 -8
- DIRAC/WorkloadManagementSystem/DB/JobDB.py +89 -132
- DIRAC/WorkloadManagementSystem/DB/JobDB.sql +8 -8
- DIRAC/WorkloadManagementSystem/DB/JobDBUtils.py +18 -147
- DIRAC/WorkloadManagementSystem/DB/JobLoggingDB.py +19 -6
- DIRAC/WorkloadManagementSystem/DB/JobParametersDB.py +9 -9
- DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.py +16 -5
- DIRAC/WorkloadManagementSystem/DB/PilotAgentsDB.sql +3 -3
- DIRAC/WorkloadManagementSystem/DB/SandboxMetadataDB.py +44 -82
- DIRAC/WorkloadManagementSystem/DB/StatusUtils.py +125 -0
- DIRAC/WorkloadManagementSystem/DB/tests/Test_JobDB.py +1 -1
- DIRAC/WorkloadManagementSystem/DB/tests/Test_StatusUtils.py +28 -0
- DIRAC/WorkloadManagementSystem/Executor/JobSanity.py +5 -4
- DIRAC/WorkloadManagementSystem/Executor/JobScheduling.py +4 -0
- DIRAC/WorkloadManagementSystem/FutureClient/JobStateUpdateClient.py +75 -33
- DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapper.py +22 -11
- DIRAC/WorkloadManagementSystem/JobWrapper/JobWrapperTemplate.py +9 -10
- DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapper.py +60 -10
- DIRAC/WorkloadManagementSystem/JobWrapper/test/Test_JobWrapperTemplate.py +4 -0
- DIRAC/WorkloadManagementSystem/Service/JobManagerHandler.py +33 -154
- DIRAC/WorkloadManagementSystem/Service/JobMonitoringHandler.py +5 -323
- DIRAC/WorkloadManagementSystem/Service/JobStateUpdateHandler.py +0 -16
- DIRAC/WorkloadManagementSystem/Service/PilotManagerHandler.py +6 -103
- DIRAC/WorkloadManagementSystem/Service/SandboxStoreHandler.py +7 -53
- DIRAC/WorkloadManagementSystem/Service/WMSAdministratorHandler.py +16 -79
- DIRAC/WorkloadManagementSystem/Service/WMSUtilities.py +4 -18
- DIRAC/WorkloadManagementSystem/Utilities/JobModel.py +28 -209
- DIRAC/WorkloadManagementSystem/Utilities/JobParameters.py +65 -3
- DIRAC/WorkloadManagementSystem/Utilities/JobStatusUtility.py +2 -64
- DIRAC/WorkloadManagementSystem/Utilities/ParametricJob.py +7 -171
- DIRAC/WorkloadManagementSystem/Utilities/PilotCStoJSONSynchronizer.py +73 -7
- DIRAC/WorkloadManagementSystem/Utilities/PilotWrapper.py +41 -11
- DIRAC/WorkloadManagementSystem/Utilities/RemoteRunner.py +16 -0
- DIRAC/WorkloadManagementSystem/Utilities/Utils.py +36 -1
- DIRAC/WorkloadManagementSystem/Utilities/jobAdministration.py +15 -0
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobModel.py +1 -15
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_ParametricJob.py +45 -128
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_PilotWrapper.py +16 -0
- DIRAC/WorkloadManagementSystem/scripts/dirac_jobexec.py +7 -2
- DIRAC/WorkloadManagementSystem/scripts/dirac_wms_pilot_job_info.py +1 -1
- DIRAC/__init__.py +62 -60
- DIRAC/tests/Utilities/testJobDefinitions.py +22 -28
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/METADATA +8 -5
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/RECORD +229 -228
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/WHEEL +1 -1
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/entry_points.txt +0 -3
- DIRAC/Core/Utilities/test/Test_List.py +0 -150
- DIRAC/Core/Utilities/test/Test_Time.py +0 -88
- DIRAC/Resources/Computing/PilotBundle.py +0 -70
- DIRAC/TransformationSystem/scripts/dirac_transformation_archive.py +0 -30
- DIRAC/TransformationSystem/scripts/dirac_transformation_clean.py +0 -30
- DIRAC/TransformationSystem/scripts/dirac_transformation_remove_output.py +0 -30
- DIRAC/WorkloadManagementSystem/Utilities/test/Test_JobManager.py +0 -58
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info/licenses}/LICENSE +0 -0
- {DIRAC-9.0.0a42.dist-info → dirac-9.0.7.dist-info}/top_level.txt +0 -0
|
@@ -11,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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
|
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.
|
|
20
|
-
self.log = gLogger.getSubLogger(self.
|
|
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(
|
|
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 {
|
|
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(
|
|
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
|
|
58
|
-
self.log.warn(f"Attempted to write catalog also to {
|
|
59
|
-
|
|
60
|
-
|
|
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
|
|
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
|
|
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
|
|
267
|
-
|
|
268
|
-
# List of
|
|
269
|
-
|
|
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
|