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
|
@@ -1,260 +1,17 @@
|
|
|
1
|
-
"""
|
|
2
|
-
DIRAC TimeUtilities module
|
|
3
|
-
Support for basic Date and Time operations
|
|
4
|
-
based on system datetime module.
|
|
5
|
-
|
|
6
|
-
It provides common interface to UTC timestamps,
|
|
7
|
-
converter to string types and back.
|
|
8
|
-
|
|
9
|
-
Useful timedelta constant are also provided to
|
|
10
|
-
define time intervals.
|
|
11
|
-
|
|
12
|
-
Notice: datetime.timedelta objects allow multiplication and division by interger
|
|
13
|
-
but not by float. Thus:
|
|
14
|
-
|
|
15
|
-
- DIRAC.TimeUtilities.second * 1.5 is not allowed
|
|
16
|
-
- DIRAC.TimeUtilities.second * 3 / 2 is allowed
|
|
1
|
+
"""Backward compatibility wrapper - moved to DIRACCommon
|
|
17
2
|
|
|
18
|
-
|
|
19
|
-
|
|
3
|
+
This module has been moved to DIRACCommon.Core.Utilities.TimeUtilities to avoid
|
|
4
|
+
circular dependencies and allow DiracX to use these utilities without
|
|
5
|
+
triggering DIRAC's global state initialization.
|
|
20
6
|
|
|
7
|
+
All exports are maintained for backward compatibility.
|
|
21
8
|
"""
|
|
22
|
-
import
|
|
23
|
-
import sys
|
|
24
|
-
import time
|
|
25
|
-
|
|
26
|
-
from DIRAC import gLogger
|
|
27
|
-
|
|
28
|
-
# Some useful constants for time operations
|
|
29
|
-
microsecond = datetime.timedelta(microseconds=1)
|
|
30
|
-
second = datetime.timedelta(seconds=1)
|
|
31
|
-
minute = datetime.timedelta(minutes=1)
|
|
32
|
-
hour = datetime.timedelta(hours=1)
|
|
33
|
-
day = datetime.timedelta(days=1)
|
|
34
|
-
week = datetime.timedelta(days=7)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def timeThis(method):
|
|
38
|
-
"""Function to be used as a decorator for timing other functions/methods"""
|
|
39
|
-
|
|
40
|
-
def timed(*args, **kw):
|
|
41
|
-
"""What actually times"""
|
|
42
|
-
ts = time.time()
|
|
43
|
-
result = method(*args, **kw)
|
|
44
|
-
if sys.stdout.isatty():
|
|
45
|
-
return result
|
|
46
|
-
te = time.time()
|
|
47
|
-
|
|
48
|
-
pre = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC ")
|
|
49
|
-
|
|
50
|
-
try:
|
|
51
|
-
pre += args[0].log.getName() + "/" + args[0].log.getSubName() + " TIME: " + args[0].transString
|
|
52
|
-
except AttributeError:
|
|
53
|
-
try:
|
|
54
|
-
pre += args[0].log.getName() + " TIME: " + args[0].transString
|
|
55
|
-
except AttributeError:
|
|
56
|
-
try:
|
|
57
|
-
pre += args[0].log.getName() + "/" + args[0].log.getSubName() + " TIME: "
|
|
58
|
-
except AttributeError:
|
|
59
|
-
pre += "TIME: "
|
|
60
|
-
except IndexError:
|
|
61
|
-
pre += "TIME: "
|
|
62
|
-
|
|
63
|
-
argsLen = ""
|
|
64
|
-
if args:
|
|
65
|
-
try:
|
|
66
|
-
if isinstance(args[1], (list, dict)):
|
|
67
|
-
argsLen = f"arguments len: {len(args[1])}"
|
|
68
|
-
except IndexError:
|
|
69
|
-
if kw:
|
|
70
|
-
try:
|
|
71
|
-
if isinstance(list(list(kw.items())[0])[1], (list, dict)):
|
|
72
|
-
argsLen = f"arguments len: {len(list(list(kw.items())[0])[1])}"
|
|
73
|
-
except IndexError:
|
|
74
|
-
argsLen = ""
|
|
75
|
-
|
|
76
|
-
gLogger.info(f"{pre} Exec time ===> function {method.__name__!r} {argsLen} -> {te - ts:2.2f} sec")
|
|
77
|
-
return result
|
|
78
|
-
|
|
79
|
-
return timed
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def toEpoch(dateTimeObject=None):
|
|
83
|
-
"""
|
|
84
|
-
Get seconds since epoch. Accepts datetime or date objects
|
|
85
|
-
"""
|
|
86
|
-
return toEpochMilliSeconds(dateTimeObject) // 1000
|
|
9
|
+
from functools import partial
|
|
87
10
|
|
|
11
|
+
# Re-export everything from DIRACCommon for backward compatibility
|
|
12
|
+
from DIRACCommon.Core.Utilities.TimeUtilities import * # noqa: F401, F403
|
|
88
13
|
|
|
89
|
-
|
|
90
|
-
"""
|
|
91
|
-
Get milliseconds since epoch
|
|
92
|
-
"""
|
|
93
|
-
if dateTimeObject is None:
|
|
94
|
-
dateTimeObject = datetime.datetime.utcnow()
|
|
95
|
-
if dateTimeObject.resolution == datetime.timedelta(days=1):
|
|
96
|
-
# Add time information corresponding to midnight UTC if it's a datetime.date
|
|
97
|
-
dateTimeObject = datetime.datetime.combine(
|
|
98
|
-
dateTimeObject, datetime.time.min.replace(tzinfo=datetime.timezone.utc)
|
|
99
|
-
)
|
|
100
|
-
posixTime = dateTimeObject.replace(tzinfo=datetime.timezone.utc).timestamp()
|
|
101
|
-
return int(posixTime * 1000)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def fromEpoch(epoch):
|
|
105
|
-
"""
|
|
106
|
-
Get datetime object from epoch
|
|
107
|
-
"""
|
|
108
|
-
# Check if the timestamp is in milliseconds
|
|
109
|
-
if epoch > 10**17: # nanoseconds
|
|
110
|
-
epoch /= 1000**3
|
|
111
|
-
elif epoch > 10**14: # microseconds
|
|
112
|
-
epoch /= 1000**2
|
|
113
|
-
elif epoch > 10**11: # milliseconds
|
|
114
|
-
epoch /= 1000
|
|
115
|
-
return datetime.datetime.utcfromtimestamp(epoch)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def toString(myDate=None):
|
|
119
|
-
"""
|
|
120
|
-
Convert to String
|
|
121
|
-
if argument type is neither _dateTimeType, _dateType, nor _timeType
|
|
122
|
-
the current dateTime converted to String is returned instead
|
|
123
|
-
|
|
124
|
-
Notice: datetime.timedelta are converted to strings using the format:
|
|
125
|
-
[day] days [hour]:[min]:[sec]:[microsec]
|
|
126
|
-
where hour, min, sec, microsec are always positive integers,
|
|
127
|
-
and day carries the sign.
|
|
128
|
-
To keep internal consistency we are using:
|
|
129
|
-
[hour]:[min]:[sec]:[microsec]
|
|
130
|
-
where min, sec, microsec are always positive integers and hour carries the sign.
|
|
131
|
-
"""
|
|
132
|
-
if isinstance(myDate, datetime.date):
|
|
133
|
-
return str(myDate)
|
|
134
|
-
|
|
135
|
-
elif isinstance(myDate, datetime.time):
|
|
136
|
-
return "%02d:%02d:%02d.%06d" % (
|
|
137
|
-
myDate.days * 24 + myDate.seconds / 3600,
|
|
138
|
-
myDate.seconds % 3600 / 60,
|
|
139
|
-
myDate.seconds % 60,
|
|
140
|
-
myDate.microseconds,
|
|
141
|
-
)
|
|
142
|
-
else:
|
|
143
|
-
return toString(datetime.datetime.utcnow())
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def fromString(myDate=None):
|
|
147
|
-
"""
|
|
148
|
-
Convert date/time/datetime String back to appropriated objects
|
|
149
|
-
|
|
150
|
-
The format of the string it is assume to be that returned by toString method.
|
|
151
|
-
See notice on toString method
|
|
152
|
-
On Error, return None
|
|
153
|
-
|
|
154
|
-
:param myDate: the date string to be converted
|
|
155
|
-
:type myDate: str or datetime.datetime
|
|
156
|
-
"""
|
|
157
|
-
if isinstance(myDate, datetime.datetime):
|
|
158
|
-
return myDate
|
|
159
|
-
if isinstance(myDate, str):
|
|
160
|
-
if myDate.find(" ") > 0:
|
|
161
|
-
dateTimeTuple = myDate.split(" ")
|
|
162
|
-
dateTuple = dateTimeTuple[0].split("-")
|
|
163
|
-
try:
|
|
164
|
-
return datetime.datetime(year=dateTuple[0], month=dateTuple[1], day=dateTuple[2]) + fromString(
|
|
165
|
-
dateTimeTuple[1]
|
|
166
|
-
)
|
|
167
|
-
# return datetime.datetime.utcnow().combine( fromString( dateTimeTuple[0] ),
|
|
168
|
-
# fromString( dateTimeTuple[1] ) )
|
|
169
|
-
except Exception:
|
|
170
|
-
try:
|
|
171
|
-
return datetime.datetime(
|
|
172
|
-
year=int(dateTuple[0]), month=int(dateTuple[1]), day=int(dateTuple[2])
|
|
173
|
-
) + fromString(dateTimeTuple[1])
|
|
174
|
-
except ValueError:
|
|
175
|
-
return None
|
|
176
|
-
# return datetime.datetime.utcnow().combine( fromString( dateTimeTuple[0] ),
|
|
177
|
-
# fromString( dateTimeTuple[1] ) )
|
|
178
|
-
elif myDate.find(":") > 0:
|
|
179
|
-
timeTuple = myDate.replace(".", ":").split(":")
|
|
180
|
-
try:
|
|
181
|
-
if len(timeTuple) == 4:
|
|
182
|
-
return datetime.timedelta(
|
|
183
|
-
hours=int(timeTuple[0]),
|
|
184
|
-
minutes=int(timeTuple[1]),
|
|
185
|
-
seconds=int(timeTuple[2]),
|
|
186
|
-
microseconds=int(timeTuple[3]),
|
|
187
|
-
)
|
|
188
|
-
elif len(timeTuple) == 3:
|
|
189
|
-
try:
|
|
190
|
-
return datetime.timedelta(
|
|
191
|
-
hours=int(timeTuple[0]),
|
|
192
|
-
minutes=int(timeTuple[1]),
|
|
193
|
-
seconds=int(timeTuple[2]),
|
|
194
|
-
microseconds=0,
|
|
195
|
-
)
|
|
196
|
-
except ValueError:
|
|
197
|
-
return None
|
|
198
|
-
else:
|
|
199
|
-
return None
|
|
200
|
-
except Exception:
|
|
201
|
-
return None
|
|
202
|
-
elif myDate.find("-") > 0:
|
|
203
|
-
dateTuple = myDate.split("-")
|
|
204
|
-
try:
|
|
205
|
-
return datetime.date(int(dateTuple[0]), int(dateTuple[1]), int(dateTuple[2]))
|
|
206
|
-
except Exception:
|
|
207
|
-
return None
|
|
208
|
-
|
|
209
|
-
return None
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
class timeInterval:
|
|
213
|
-
"""
|
|
214
|
-
Simple class to define a timeInterval object able to check if a given
|
|
215
|
-
dateTime is inside
|
|
216
|
-
"""
|
|
217
|
-
|
|
218
|
-
def __init__(self, initialDateTime, intervalTimeDelta):
|
|
219
|
-
"""
|
|
220
|
-
Initialization method, it requires the initial dateTime and the
|
|
221
|
-
timedelta that define the limits.
|
|
222
|
-
The upper limit is not included thus it is [begin,end)
|
|
223
|
-
If not properly initialized an error flag is set, and subsequent calls
|
|
224
|
-
to any method will return None
|
|
225
|
-
"""
|
|
226
|
-
if not isinstance(initialDateTime, datetime.datetime) or not isinstance(intervalTimeDelta, datetime.timedelta):
|
|
227
|
-
self.__error = True
|
|
228
|
-
return None
|
|
229
|
-
self.__error = False
|
|
230
|
-
if intervalTimeDelta.days < 0:
|
|
231
|
-
self.__startDateTime = initialDateTime + intervalTimeDelta
|
|
232
|
-
self.__endDateTime = initialDateTime
|
|
233
|
-
else:
|
|
234
|
-
self.__startDateTime = initialDateTime
|
|
235
|
-
self.__endDateTime = initialDateTime + intervalTimeDelta
|
|
236
|
-
|
|
237
|
-
def includes(self, myDateTime):
|
|
238
|
-
""" """
|
|
239
|
-
if self.__error:
|
|
240
|
-
return None
|
|
241
|
-
if not isinstance(myDateTime, datetime.datetime):
|
|
242
|
-
return None
|
|
243
|
-
if myDateTime < self.__startDateTime:
|
|
244
|
-
return False
|
|
245
|
-
if myDateTime >= self.__endDateTime:
|
|
246
|
-
return False
|
|
247
|
-
return True
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
def queryTime(f):
|
|
251
|
-
"""Decorator to measure the function call time"""
|
|
14
|
+
from DIRAC import gLogger
|
|
252
15
|
|
|
253
|
-
def measureQueryTime(*args, **kwargs):
|
|
254
|
-
start = time.time()
|
|
255
|
-
result = f(*args, **kwargs)
|
|
256
|
-
if result["OK"] and "QueryTime" not in result:
|
|
257
|
-
result["QueryTime"] = time.time() - start
|
|
258
|
-
return result
|
|
259
16
|
|
|
260
|
-
|
|
17
|
+
timeThis = partial(timeThis, logger_info=gLogger.info)
|
|
@@ -19,9 +19,6 @@ def jdl_monkey_business(monkeypatch):
|
|
|
19
19
|
monkeypatch.setattr("DIRAC.Core.Base.API.getSites", lambda: S_OK(["LCG.IN2P3.fr"]))
|
|
20
20
|
monkeypatch.setattr("DIRAC.WorkloadManagementSystem.Utilities.JobModel.getSites", lambda: S_OK(["LCG.IN2P3.fr"]))
|
|
21
21
|
monkeypatch.setattr("DIRAC.Interfaces.API.Job.getDIRACPlatforms", lambda: S_OK("x86_64-slc6-gcc49-opt"))
|
|
22
|
-
monkeypatch.setattr(
|
|
23
|
-
"DIRAC.WorkloadManagementSystem.Utilities.JobModel.getDIRACPlatforms", lambda: S_OK("x86_64-slc6-gcc49-opt")
|
|
24
|
-
)
|
|
25
22
|
yield
|
|
26
23
|
|
|
27
24
|
|
|
@@ -29,50 +29,50 @@ def test_base():
|
|
|
29
29
|
time.sleep(1)
|
|
30
30
|
p = Profiler(mainProcess.pid)
|
|
31
31
|
res = p.pid()
|
|
32
|
-
assert res["OK"] is True
|
|
32
|
+
assert res["OK"] is True, res
|
|
33
33
|
res = p.status()
|
|
34
|
-
assert res["OK"] is True
|
|
34
|
+
assert res["OK"] is True, res
|
|
35
35
|
res = p.runningTime()
|
|
36
|
-
assert res["OK"] is True
|
|
36
|
+
assert res["OK"] is True, res
|
|
37
37
|
assert res["Value"] > 0
|
|
38
38
|
|
|
39
39
|
res = p.memoryUsage()
|
|
40
|
-
assert res["OK"] is True
|
|
40
|
+
assert res["OK"] is True, res
|
|
41
41
|
assert res["Value"] > 0
|
|
42
42
|
resWC = p.memoryUsage(withChildren=True)
|
|
43
|
-
assert resWC["OK"] is True
|
|
43
|
+
assert resWC["OK"] is True, res
|
|
44
44
|
assert resWC["Value"] > 0
|
|
45
45
|
assert resWC["Value"] >= res["Value"]
|
|
46
46
|
|
|
47
47
|
res = p.vSizeUsage()
|
|
48
|
-
assert res["OK"] is True
|
|
48
|
+
assert res["OK"] is True, res
|
|
49
49
|
assert res["Value"] > 0
|
|
50
50
|
resWC = p.vSizeUsage(withChildren=True)
|
|
51
|
-
assert resWC["OK"] is True
|
|
51
|
+
assert resWC["OK"] is True, res
|
|
52
52
|
assert resWC["Value"] > 0
|
|
53
53
|
assert resWC["Value"] >= res["Value"]
|
|
54
54
|
|
|
55
55
|
res = p.vSizeUsage()
|
|
56
|
-
assert res["OK"] is True
|
|
56
|
+
assert res["OK"] is True, res
|
|
57
57
|
assert res["Value"] > 0
|
|
58
58
|
resWC = p.vSizeUsage(withChildren=True)
|
|
59
|
-
assert resWC["OK"] is True
|
|
59
|
+
assert resWC["OK"] is True, res
|
|
60
60
|
assert resWC["Value"] > 0
|
|
61
61
|
assert resWC["Value"] >= res["Value"]
|
|
62
62
|
|
|
63
63
|
res = p.numThreads()
|
|
64
|
-
assert res["OK"] is True
|
|
64
|
+
assert res["OK"] is True, res
|
|
65
65
|
assert res["Value"] > 0
|
|
66
66
|
resWC = p.numThreads(withChildren=True)
|
|
67
|
-
assert resWC["OK"] is True
|
|
67
|
+
assert resWC["OK"] is True, res
|
|
68
68
|
assert resWC["Value"] > 0
|
|
69
69
|
assert resWC["Value"] >= res["Value"]
|
|
70
70
|
|
|
71
71
|
res = p.cpuPercentage()
|
|
72
|
-
assert res["OK"] is True
|
|
72
|
+
assert res["OK"] is True, res
|
|
73
73
|
assert res["Value"] >= 0
|
|
74
74
|
resWC = p.cpuPercentage(withChildren=True)
|
|
75
|
-
assert resWC["OK"] is True
|
|
75
|
+
assert resWC["OK"] is True, res
|
|
76
76
|
assert resWC["Value"] >= 0
|
|
77
77
|
assert resWC["Value"] >= res["Value"]
|
|
78
78
|
|
|
@@ -88,13 +88,13 @@ def test_cpuUsage():
|
|
|
88
88
|
time.sleep(2)
|
|
89
89
|
p = Profiler(mainProcess.pid)
|
|
90
90
|
res = p.pid()
|
|
91
|
-
assert res["OK"] is True
|
|
91
|
+
assert res["OK"] is True, res
|
|
92
92
|
res = p.status()
|
|
93
|
-
assert res["OK"] is True
|
|
93
|
+
assert res["OK"] is True, res
|
|
94
94
|
|
|
95
95
|
# user
|
|
96
96
|
res = p.cpuUsageUser()
|
|
97
|
-
assert res["OK"] is True
|
|
97
|
+
assert res["OK"] is True, res
|
|
98
98
|
assert res["Value"] > 0
|
|
99
99
|
resC = p.cpuUsageUser(withChildren=True)
|
|
100
100
|
assert resC["OK"] is True
|
|
@@ -102,7 +102,7 @@ def test_cpuUsage():
|
|
|
102
102
|
assert resC["Value"] >= res["Value"]
|
|
103
103
|
|
|
104
104
|
res = p.cpuUsageUser()
|
|
105
|
-
assert res["OK"] is True
|
|
105
|
+
assert res["OK"] is True, res
|
|
106
106
|
assert res["Value"] > 0
|
|
107
107
|
resC = p.cpuUsageUser(withChildren=True)
|
|
108
108
|
assert resC["OK"] is True
|
|
@@ -121,15 +121,15 @@ def test_cpuUsage():
|
|
|
121
121
|
|
|
122
122
|
# system
|
|
123
123
|
res = p.cpuUsageSystem()
|
|
124
|
-
assert res["OK"] is True
|
|
124
|
+
assert res["OK"] is True, res
|
|
125
125
|
assert res["Value"] >= 0
|
|
126
126
|
resWC = p.cpuUsageSystem(withChildren=True)
|
|
127
|
-
assert resWC["OK"] is True
|
|
127
|
+
assert resWC["OK"] is True, res
|
|
128
128
|
assert resWC["Value"] >= 0
|
|
129
129
|
assert resWC["Value"] >= res["Value"]
|
|
130
130
|
|
|
131
131
|
res = p.cpuUsageSystem()
|
|
132
|
-
assert res["OK"] is True
|
|
132
|
+
assert res["OK"] is True, res
|
|
133
133
|
assert res["Value"] > 0
|
|
134
134
|
resC = p.cpuUsageSystem(withChildren=True)
|
|
135
135
|
assert resC["OK"] is True
|
|
@@ -25,7 +25,7 @@ def main():
|
|
|
25
25
|
localCfg.setConfigurationForAgent(agentName)
|
|
26
26
|
localCfg.addDefaultEntry("/DIRAC/Security/UseServerCertificate", "yes")
|
|
27
27
|
localCfg.addDefaultEntry("LogColor", True)
|
|
28
|
-
resultDict = localCfg.loadUserData()
|
|
28
|
+
resultDict = localCfg.loadUserData(requireSuccessfulSync=True)
|
|
29
29
|
if not resultDict["OK"]:
|
|
30
30
|
gLogger.error("There were errors when loading configuration", resultDict["Message"])
|
|
31
31
|
sys.exit(1)
|
|
@@ -1,47 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
"""
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Starts a DIRAC command inside an apptainer container."""
|
|
3
3
|
|
|
4
4
|
import os
|
|
5
|
-
import shutil
|
|
6
5
|
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
import DIRAC
|
|
9
9
|
from DIRAC import S_ERROR, gConfig, gLogger
|
|
10
10
|
from DIRAC.Core.Base.Script import Script
|
|
11
|
+
from DIRAC.Core.Security.Locations import getCAsLocation, getProxyLocation, getVOMSLocation
|
|
12
|
+
from DIRAC.Core.Utilities.Os import safe_listdir
|
|
11
13
|
from DIRAC.Core.Utilities.Subprocess import systemCall
|
|
12
14
|
|
|
13
|
-
CONTAINER_WRAPPER = """#!/bin/bash
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
echo "Finishing inner container wrapper scripts at `date`."
|
|
22
|
-
"""
|
|
16
|
+
def generate_container_wrapper(dirac_env_var, diracos_env_var, etc_dir, rc_script, command, include_proxy=True):
|
|
17
|
+
lines = [
|
|
18
|
+
"#!/bin/bash",
|
|
19
|
+
f"export DIRAC={dirac_env_var}",
|
|
20
|
+
f"export DIRACOS={diracos_env_var}",
|
|
21
|
+
]
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
if include_proxy:
|
|
24
|
+
lines.append("export X509_USER_PROXY=/etc/proxy")
|
|
25
25
|
|
|
26
|
+
lines.extend(
|
|
27
|
+
[
|
|
28
|
+
"export X509_CERT_DIR=/etc/grid-security/certificates",
|
|
29
|
+
"export X509_VOMS_DIR=/etc/grid-security/vomsdir",
|
|
30
|
+
"export X509_VOMSES=/etc/grid-security/vomses",
|
|
31
|
+
f"export DIRACSYSCONFIG={etc_dir}/dirac.cfg",
|
|
32
|
+
f"source {rc_script}",
|
|
33
|
+
command,
|
|
34
|
+
]
|
|
35
|
+
)
|
|
26
36
|
|
|
27
|
-
|
|
28
|
-
"""Gets the environment for use within the container.
|
|
29
|
-
We blank almost everything to prevent contamination from the host system.
|
|
30
|
-
"""
|
|
37
|
+
return "\n".join(lines)
|
|
31
38
|
|
|
32
|
-
payloadEnv = {k: v for k, v in os.environ.items()}
|
|
33
|
-
payloadEnv["TMP"] = "/tmp"
|
|
34
|
-
payloadEnv["TMPDIR"] = "/tmp"
|
|
35
|
-
payloadEnv["X509_USER_PROXY"] = os.path.join("tmp", "proxy")
|
|
36
|
-
payloadEnv["DIRACSYSCONFIG"] = os.path.join("tmp", "dirac.cfg")
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
CONTAINER_DEFROOT = "" # Should add something like "/cvmfs/dirac.egi.eu/container/apptainer/alma9/x86_64"
|
|
39
41
|
|
|
40
42
|
|
|
41
43
|
@Script()
|
|
42
44
|
def main():
|
|
43
|
-
|
|
44
|
-
command = Script.getPositionalArgs(group=True)
|
|
45
|
+
command = sys.argv[1]
|
|
45
46
|
|
|
46
47
|
user_image = None
|
|
47
48
|
Script.registerSwitch("i:", "image=", " apptainer image to use")
|
|
@@ -50,41 +51,66 @@ def main():
|
|
|
50
51
|
if switch[0].lower() == "i" or switch[0].lower() == "image":
|
|
51
52
|
user_image = switch[1]
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
54
|
+
cwd = os.path.realpath(os.getcwd())
|
|
55
|
+
dirac_env_var = os.environ.get("DIRAC", cwd)
|
|
56
|
+
diracos_env_var = os.environ.get("DIRACOS", cwd)
|
|
57
|
+
etc_dir = os.path.join(DIRAC.rootPath, "etc")
|
|
58
|
+
rc_script = os.path.join(os.path.realpath(sys.base_prefix), "diracosrc")
|
|
59
|
+
|
|
60
|
+
include_proxy = True
|
|
61
|
+
proxy_location = getProxyLocation()
|
|
62
|
+
if not proxy_location:
|
|
63
|
+
include_proxy = False
|
|
64
|
+
|
|
65
|
+
with open("dirac_container.sh", "w", encoding="utf-8") as fd:
|
|
66
|
+
script = generate_container_wrapper(
|
|
67
|
+
dirac_env_var, diracos_env_var, etc_dir, rc_script, command, include_proxy=include_proxy
|
|
68
|
+
)
|
|
69
|
+
fd.write(script)
|
|
70
|
+
os.chmod("dirac_container.sh", 0o755)
|
|
71
|
+
|
|
72
|
+
# Now let's construct the apptainer command
|
|
68
73
|
cmd = ["apptainer", "exec"]
|
|
69
74
|
cmd.extend(["--contain"]) # use minimal /dev and empty other directories (e.g. /tmp and $HOME)
|
|
70
75
|
cmd.extend(["--ipc"]) # run container in a new IPC namespace
|
|
71
|
-
cmd.extend(["--
|
|
72
|
-
cmd.extend(["--
|
|
73
|
-
|
|
76
|
+
cmd.extend(["--pid"]) # run container in a new PID namespace
|
|
77
|
+
cmd.extend(["--bind", cwd]) # bind current directory for dirac_container.sh
|
|
78
|
+
if proxy_location:
|
|
79
|
+
cmd.extend(["--bind", f"{proxy_location}:/etc/proxy"]) # bind proxy file
|
|
80
|
+
cmd.extend(["--bind", f"{getCAsLocation()}:/etc/grid-security/certificates"]) # X509_CERT_DIR
|
|
81
|
+
voms_location = Path(getVOMSLocation())
|
|
82
|
+
cmd.extend(["--bind", f"{voms_location}:/etc/grid-security/vomsdir"]) # X509_VOMS_DIR
|
|
83
|
+
vomses_location = voms_location.parent / "vomses"
|
|
84
|
+
cmd.extend(["--bind", f"{vomses_location}:/etc/grid-security/vomses"]) # X509_VOMSES
|
|
85
|
+
cmd.extend(["--bind", "{0}:{0}:ro".format(etc_dir)]) # etc dir for dirac.cfg
|
|
86
|
+
cmd.extend(["--bind", "{0}:{0}:ro".format(os.path.join(os.path.realpath(sys.base_prefix)))]) # code dir
|
|
87
|
+
# here bind optional paths
|
|
88
|
+
for bind_path in gConfig.getValue("/Resources/Computing/Singularity/BindPaths", []):
|
|
89
|
+
if safe_listdir(bind_path):
|
|
90
|
+
cmd.extend(["--bind", f"{bind_path}:{bind_path}"])
|
|
91
|
+
else:
|
|
92
|
+
gLogger.warn(f"Bind path {bind_path} does not exist, skipping")
|
|
93
|
+
cmd.extend(["--cwd", cwd]) # set working directory
|
|
74
94
|
|
|
75
95
|
rootImage = user_image or gConfig.getValue("/Resources/Computing/Singularity/ContainerRoot") or CONTAINER_DEFROOT
|
|
76
96
|
|
|
77
97
|
if os.path.isdir(rootImage) or os.path.isfile(rootImage):
|
|
78
|
-
cmd.extend([rootImage,
|
|
98
|
+
cmd.extend([rootImage, f"{cwd}/dirac_container.sh"])
|
|
79
99
|
else:
|
|
80
100
|
# if we are here is because there's no image, or it is not accessible (e.g. not on CVMFS)
|
|
81
101
|
gLogger.error("Apptainer image to exec not found: ", rootImage)
|
|
82
102
|
return S_ERROR("Failed to find Apptainer image to exec")
|
|
83
103
|
|
|
84
|
-
gLogger.debug(f"Execute Apptainer command: {cmd}")
|
|
85
|
-
result = systemCall(0, cmd
|
|
104
|
+
gLogger.debug(f"Execute Apptainer command: {' '.join(cmd)}")
|
|
105
|
+
result = systemCall(0, cmd)
|
|
86
106
|
if not result["OK"]:
|
|
107
|
+
gLogger.error(result["Message"])
|
|
87
108
|
DIRAC.exit(1)
|
|
109
|
+
if result["Value"][0] != 0:
|
|
110
|
+
gLogger.error("Apptainer command failed with exit code", result["Value"][0])
|
|
111
|
+
gLogger.error("Command output:", result["Value"])
|
|
112
|
+
DIRAC.exit(2)
|
|
113
|
+
gLogger.notice(result["Value"][1])
|
|
88
114
|
|
|
89
115
|
|
|
90
116
|
if __name__ == "__main__":
|
|
@@ -99,9 +99,7 @@ class Params:
|
|
|
99
99
|
self.includeAllServers = True
|
|
100
100
|
|
|
101
101
|
def setSetup(self, optionValue):
|
|
102
|
-
|
|
103
|
-
DIRAC.gConfig.setOptionValue("/DIRAC/Setup", self.setup)
|
|
104
|
-
DIRAC.gConfig.setOptionValue(cfgInstallPath("Setup"), self.setup)
|
|
102
|
+
DIRAC.gLogger.warn("Ignoring Setup option as it is not used for DIRAC v9.0+")
|
|
105
103
|
return DIRAC.S_OK()
|
|
106
104
|
|
|
107
105
|
def setSiteName(self, optionValue):
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
"""
|
|
3
3
|
Create a new DB in the MySQL server
|
|
4
4
|
"""
|
|
5
|
+
from DIRAC import exit as DIRACExit
|
|
6
|
+
from DIRAC import gConfig, gLogger
|
|
5
7
|
from DIRAC.Core.Base.Script import Script
|
|
6
8
|
|
|
7
9
|
|
|
@@ -12,24 +14,40 @@ def main():
|
|
|
12
14
|
_, args = Script.parseCommandLine()
|
|
13
15
|
|
|
14
16
|
# Script imports
|
|
15
|
-
from DIRAC import
|
|
17
|
+
from DIRAC.ConfigurationSystem.Client.Helpers.CSGlobals import useServerCertificate
|
|
18
|
+
from DIRAC.Core.Security.ProxyInfo import getProxyInfo
|
|
16
19
|
from DIRAC.FrameworkSystem.Client.ComponentInstaller import gComponentInstaller
|
|
17
20
|
from DIRAC.FrameworkSystem.Utilities import MonitoringUtilities
|
|
18
21
|
|
|
22
|
+
user = "DIRAC"
|
|
23
|
+
|
|
19
24
|
gComponentInstaller.exitOnError = True
|
|
20
25
|
gComponentInstaller.getMySQLPasswords()
|
|
21
26
|
for db in args:
|
|
22
27
|
result = gComponentInstaller.installDatabase(db)
|
|
23
28
|
if not result["OK"]:
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
gLogger.error(f"Failed to correctly install {db}:", result["Message"])
|
|
30
|
+
DIRACExit(1)
|
|
26
31
|
extension, system = result["Value"]
|
|
27
|
-
gComponentInstaller.addDatabaseOptionsToCS(gConfig, system, db, overwrite=True)
|
|
32
|
+
result = gComponentInstaller.addDatabaseOptionsToCS(gConfig, system, db, overwrite=True)
|
|
33
|
+
if not result["OK"]:
|
|
34
|
+
gLogger.error("Failed to add database options to CS:", result["Message"])
|
|
35
|
+
DIRACExit(1)
|
|
28
36
|
|
|
29
37
|
if db != "InstalledComponentsDB":
|
|
30
|
-
|
|
38
|
+
# get the user that installed the DB
|
|
39
|
+
if not useServerCertificate():
|
|
40
|
+
result = getProxyInfo()
|
|
41
|
+
if not result["OK"]:
|
|
42
|
+
return result
|
|
43
|
+
proxyInfo = result["Value"]
|
|
44
|
+
if "username" in proxyInfo:
|
|
45
|
+
user = proxyInfo["username"]
|
|
46
|
+
|
|
47
|
+
result = MonitoringUtilities.monitorInstallation("DB", system, db, user=user)
|
|
31
48
|
if not result["OK"]:
|
|
32
|
-
|
|
49
|
+
gLogger.error("Failed to register installation in database:", result["Message"])
|
|
50
|
+
DIRACExit(1)
|
|
33
51
|
|
|
34
52
|
|
|
35
53
|
if __name__ == "__main__":
|