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
|
@@ -48,13 +48,6 @@ class TransformationClient(Client):
|
|
|
48
48
|
|
|
49
49
|
getFileSummary(lfns)
|
|
50
50
|
exists(lfns)
|
|
51
|
-
|
|
52
|
-
Web monitoring tools
|
|
53
|
-
|
|
54
|
-
getDistinctAttributeValues(attribute, selectDict)
|
|
55
|
-
getTransformationStatusCounters()
|
|
56
|
-
getTransformationSummary()
|
|
57
|
-
getTransformationSummaryWeb(selectDict, sortList, startItem, maxItems)
|
|
58
51
|
"""
|
|
59
52
|
|
|
60
53
|
def __init__(self, **kwargs):
|
|
@@ -9,6 +9,8 @@ Utilities for Transformation system
|
|
|
9
9
|
import ast
|
|
10
10
|
import random
|
|
11
11
|
|
|
12
|
+
from cachetools import LRUCache, cachedmethod
|
|
13
|
+
from cachetools.keys import hashkey
|
|
12
14
|
from DIRAC import S_OK, S_ERROR, gLogger
|
|
13
15
|
|
|
14
16
|
from DIRAC.Core.Utilities.List import breakListIntoChunks
|
|
@@ -22,6 +24,9 @@ from DIRAC.Resources.Catalog.FileCatalog import FileCatalog
|
|
|
22
24
|
from DIRAC.Resources.Storage.StorageElement import StorageElement
|
|
23
25
|
from DIRAC.TransformationSystem.Client.TransformationClient import TransformationClient
|
|
24
26
|
|
|
27
|
+
# Module-level cache for isSameSEInList method (shared across PluginUtilities instances)
|
|
28
|
+
_is_same_se_in_list_cache = LRUCache(maxsize=1024)
|
|
29
|
+
|
|
25
30
|
|
|
26
31
|
class PluginUtilities:
|
|
27
32
|
"""
|
|
@@ -400,6 +405,10 @@ class PluginUtilities:
|
|
|
400
405
|
|
|
401
406
|
return StorageElement(se1).isSameSE(StorageElement(se2))
|
|
402
407
|
|
|
408
|
+
@cachedmethod(
|
|
409
|
+
lambda self: _is_same_se_in_list_cache,
|
|
410
|
+
key=lambda _, a, b: hashkey(a, *sorted(b)),
|
|
411
|
+
)
|
|
403
412
|
def isSameSEInList(self, se1, seList):
|
|
404
413
|
"""Check if an SE is the same as any in a list"""
|
|
405
414
|
if se1 in seList:
|
|
@@ -3,22 +3,12 @@
|
|
|
3
3
|
import datetime
|
|
4
4
|
|
|
5
5
|
from DIRAC import S_ERROR, S_OK
|
|
6
|
-
from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations
|
|
7
6
|
from DIRAC.Core.DISET.RequestHandler import RequestHandler
|
|
8
7
|
from DIRAC.Core.Security.Properties import SecurityProperty
|
|
9
8
|
from DIRAC.Core.Utilities.Decorators import deprecated
|
|
10
9
|
from DIRAC.Core.Utilities.DEncode import ignoreEncodeWarning
|
|
11
10
|
from DIRAC.Core.Utilities.JEncode import encode as jencode
|
|
12
11
|
from DIRAC.Core.Utilities.ObjectLoader import ObjectLoader
|
|
13
|
-
from DIRAC.RequestManagementSystem.Client.Operation import Operation
|
|
14
|
-
from DIRAC.RequestManagementSystem.Client.Request import Request
|
|
15
|
-
from DIRAC.TransformationSystem.Client import TransformationFilesStatus
|
|
16
|
-
from DIRAC.WorkloadManagementSystem.Client import JobStatus
|
|
17
|
-
|
|
18
|
-
TASKS_STATE_NAMES = ["TotalCreated", "Created"] + sorted(
|
|
19
|
-
set(JobStatus.JOB_STATES) | set(Request.ALL_STATES) | set(Operation.ALL_STATES)
|
|
20
|
-
)
|
|
21
|
-
FILES_STATE_NAMES = ["PercentProcessed", "Total"] + TransformationFilesStatus.TRANSFORMATION_FILES_STATES
|
|
22
12
|
|
|
23
13
|
|
|
24
14
|
class TransformationManagerHandlerMixin:
|
|
@@ -530,39 +520,12 @@ class TransformationManagerHandlerMixin:
|
|
|
530
520
|
"""Set metadata to a file or to a directory (path)"""
|
|
531
521
|
return cls.transformationDB.setMetadata(path, querydict)
|
|
532
522
|
|
|
533
|
-
####################################################################
|
|
534
|
-
#
|
|
535
|
-
# These are the methods used for web monitoring
|
|
536
|
-
#
|
|
537
|
-
|
|
538
|
-
# TODO Get rid of this (talk to Matvey)
|
|
539
|
-
types_getDistinctAttributeValues = [str, dict]
|
|
540
|
-
|
|
541
|
-
@classmethod
|
|
542
|
-
def export_getDistinctAttributeValues(cls, attribute, selectDict):
|
|
543
|
-
res = cls.transformationDB.getTableDistinctAttributeValues("Transformations", [attribute], selectDict)
|
|
544
|
-
if not res["OK"]:
|
|
545
|
-
return res
|
|
546
|
-
return S_OK(res["Value"][attribute])
|
|
547
|
-
|
|
548
523
|
types_getTableDistinctAttributeValues = [str, list, dict]
|
|
549
524
|
|
|
550
525
|
@classmethod
|
|
551
526
|
def export_getTableDistinctAttributeValues(cls, table, attributes, selectDict):
|
|
552
527
|
return cls.transformationDB.getTableDistinctAttributeValues(table, attributes, selectDict)
|
|
553
528
|
|
|
554
|
-
types_getTransformationStatusCounters = []
|
|
555
|
-
|
|
556
|
-
@classmethod
|
|
557
|
-
def export_getTransformationStatusCounters(cls):
|
|
558
|
-
res = cls.transformationDB.getCounters("Transformations", ["Status"], {})
|
|
559
|
-
if not res["OK"]:
|
|
560
|
-
return res
|
|
561
|
-
statDict = {}
|
|
562
|
-
for attrDict, count in res["Value"]:
|
|
563
|
-
statDict[attrDict["Status"]] = count
|
|
564
|
-
return S_OK(statDict)
|
|
565
|
-
|
|
566
529
|
types_getTransformationSummary = []
|
|
567
530
|
|
|
568
531
|
def export_getTransformationSummary(self):
|
|
@@ -587,305 +550,6 @@ class TransformationManagerHandlerMixin:
|
|
|
587
550
|
resultDict[transID] = transDict
|
|
588
551
|
return S_OK(resultDict)
|
|
589
552
|
|
|
590
|
-
types_getTabbedSummaryWeb = [str, dict, dict, list, int, int]
|
|
591
|
-
|
|
592
|
-
def export_getTabbedSummaryWeb(self, table, requestedTables, selectDict, sortList, startItem, maxItems):
|
|
593
|
-
tableDestinations = {
|
|
594
|
-
"Transformations": {
|
|
595
|
-
"TransformationFiles": ["TransformationID"],
|
|
596
|
-
"TransformationTasks": ["TransformationID"],
|
|
597
|
-
},
|
|
598
|
-
"TransformationFiles": {
|
|
599
|
-
"Transformations": ["TransformationID"],
|
|
600
|
-
"TransformationTasks": ["TransformationID", "TaskID"],
|
|
601
|
-
},
|
|
602
|
-
"TransformationTasks": {
|
|
603
|
-
"Transformations": ["TransformationID"],
|
|
604
|
-
"TransformationFiles": ["TransformationID", "TaskID"],
|
|
605
|
-
},
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
tableSelections = {
|
|
609
|
-
"Transformations": ["TransformationID", "AgentType", "Type", "TransformationGroup", "Plugin"],
|
|
610
|
-
"TransformationFiles": ["TransformationID", "TaskID", "Status", "UsedSE", "TargetSE"],
|
|
611
|
-
"TransformationTasks": ["TransformationID", "TaskID", "ExternalStatus", "TargetSE"],
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
tableTimeStamps = {
|
|
615
|
-
"Transformations": "CreationDate",
|
|
616
|
-
"TransformationFiles": "LastUpdate",
|
|
617
|
-
"TransformationTasks": "CreationTime",
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
tableStatusColumn = {
|
|
621
|
-
"Transformations": "Status",
|
|
622
|
-
"TransformationFiles": "Status",
|
|
623
|
-
"TransformationTasks": "ExternalStatus",
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
resDict = {}
|
|
627
|
-
res = self.__getTableSummaryWeb(
|
|
628
|
-
table,
|
|
629
|
-
selectDict,
|
|
630
|
-
sortList,
|
|
631
|
-
startItem,
|
|
632
|
-
maxItems,
|
|
633
|
-
selectColumns=tableSelections[table],
|
|
634
|
-
timeStamp=tableTimeStamps[table],
|
|
635
|
-
statusColumn=tableStatusColumn[table],
|
|
636
|
-
)
|
|
637
|
-
if not res["OK"]:
|
|
638
|
-
self.log.error("Failed to get Summary for table", f"{table} {res['Message']}")
|
|
639
|
-
return res
|
|
640
|
-
resDict[table] = res["Value"]
|
|
641
|
-
selections = res["Value"]["Selections"]
|
|
642
|
-
tableSelection = {}
|
|
643
|
-
for destination in tableDestinations[table].keys():
|
|
644
|
-
tableSelection[destination] = {}
|
|
645
|
-
for parameter in tableDestinations[table][destination]:
|
|
646
|
-
tableSelection[destination][parameter] = selections.get(parameter, [])
|
|
647
|
-
|
|
648
|
-
for table, paramDict in requestedTables.items():
|
|
649
|
-
sortList = paramDict.get("SortList", [])
|
|
650
|
-
startItem = paramDict.get("StartItem", 0)
|
|
651
|
-
maxItems = paramDict.get("MaxItems", 50)
|
|
652
|
-
res = self.__getTableSummaryWeb(
|
|
653
|
-
table,
|
|
654
|
-
tableSelection[table],
|
|
655
|
-
sortList,
|
|
656
|
-
startItem,
|
|
657
|
-
maxItems,
|
|
658
|
-
selectColumns=tableSelections[table],
|
|
659
|
-
timeStamp=tableTimeStamps[table],
|
|
660
|
-
statusColumn=tableStatusColumn[table],
|
|
661
|
-
)
|
|
662
|
-
if not res["OK"]:
|
|
663
|
-
self.log.error("Failed to get Summary for table", f"{table} {res['Message']}")
|
|
664
|
-
return res
|
|
665
|
-
resDict[table] = res["Value"]
|
|
666
|
-
return S_OK(resDict)
|
|
667
|
-
|
|
668
|
-
types_getTransformationsSummaryWeb = [dict, list, int, int]
|
|
669
|
-
|
|
670
|
-
def export_getTransformationsSummaryWeb(self, selectDict, sortList, startItem, maxItems):
|
|
671
|
-
return self.__getTableSummaryWeb(
|
|
672
|
-
"Transformations",
|
|
673
|
-
selectDict,
|
|
674
|
-
sortList,
|
|
675
|
-
startItem,
|
|
676
|
-
maxItems,
|
|
677
|
-
selectColumns=["TransformationID", "AgentType", "Type", "Group", "Plugin"],
|
|
678
|
-
timeStamp="CreationDate",
|
|
679
|
-
statusColumn="Status",
|
|
680
|
-
)
|
|
681
|
-
|
|
682
|
-
types_getTransformationTasksSummaryWeb = [dict, list, int, int]
|
|
683
|
-
|
|
684
|
-
def export_getTransformationTasksSummaryWeb(self, selectDict, sortList, startItem, maxItems):
|
|
685
|
-
return self.__getTableSummaryWeb(
|
|
686
|
-
"TransformationTasks",
|
|
687
|
-
selectDict,
|
|
688
|
-
sortList,
|
|
689
|
-
startItem,
|
|
690
|
-
maxItems,
|
|
691
|
-
selectColumns=["TransformationID", "ExternalStatus", "TargetSE"],
|
|
692
|
-
timeStamp="CreationTime",
|
|
693
|
-
statusColumn="ExternalStatus",
|
|
694
|
-
)
|
|
695
|
-
|
|
696
|
-
types_getTransformationFilesSummaryWeb = [dict, list, int, int]
|
|
697
|
-
|
|
698
|
-
def export_getTransformationFilesSummaryWeb(self, selectDict, sortList, startItem, maxItems):
|
|
699
|
-
return self.__getTableSummaryWeb(
|
|
700
|
-
"TransformationFiles",
|
|
701
|
-
selectDict,
|
|
702
|
-
sortList,
|
|
703
|
-
startItem,
|
|
704
|
-
maxItems,
|
|
705
|
-
selectColumns=["TransformationID", "Status", "UsedSE", "TargetSE"],
|
|
706
|
-
timeStamp="LastUpdate",
|
|
707
|
-
statusColumn="Status",
|
|
708
|
-
)
|
|
709
|
-
|
|
710
|
-
def __getTableSummaryWeb(
|
|
711
|
-
self, table, selectDict, sortList, startItem, maxItems, selectColumns=[], timeStamp=None, statusColumn="Status"
|
|
712
|
-
):
|
|
713
|
-
fromDate = selectDict.get("FromDate", None)
|
|
714
|
-
if fromDate:
|
|
715
|
-
del selectDict["FromDate"]
|
|
716
|
-
# if not fromDate:
|
|
717
|
-
# fromDate = last_update
|
|
718
|
-
toDate = selectDict.get("ToDate", None)
|
|
719
|
-
if toDate:
|
|
720
|
-
del selectDict["ToDate"]
|
|
721
|
-
# Sorting instructions. Only one for the moment.
|
|
722
|
-
if sortList:
|
|
723
|
-
orderAttribute = sortList[0][0] + ":" + sortList[0][1]
|
|
724
|
-
else:
|
|
725
|
-
orderAttribute = None
|
|
726
|
-
# Get the columns that match the selection
|
|
727
|
-
fcn = None
|
|
728
|
-
fcnName = f"get{table}"
|
|
729
|
-
if hasattr(self.transformationDB, fcnName) and callable(getattr(self.transformationDB, fcnName)):
|
|
730
|
-
fcn = getattr(self.transformationDB, fcnName)
|
|
731
|
-
if not fcn:
|
|
732
|
-
return S_ERROR(f"Unable to invoke gTransformationDB.{fcnName}, it isn't a member function")
|
|
733
|
-
res = fcn(condDict=selectDict, older=toDate, newer=fromDate, timeStamp=timeStamp, orderAttribute=orderAttribute)
|
|
734
|
-
if not res["OK"]:
|
|
735
|
-
return res
|
|
736
|
-
|
|
737
|
-
# The full list of columns in contained here
|
|
738
|
-
allRows = res["Value"]
|
|
739
|
-
# Prepare the standard structure now within the resultDict dictionary
|
|
740
|
-
resultDict = {}
|
|
741
|
-
# Create the total records entry
|
|
742
|
-
resultDict["TotalRecords"] = len(allRows)
|
|
743
|
-
|
|
744
|
-
# Get the rows which are within the selected window
|
|
745
|
-
if resultDict["TotalRecords"] == 0:
|
|
746
|
-
return S_OK(resultDict)
|
|
747
|
-
ini = startItem
|
|
748
|
-
last = ini + maxItems
|
|
749
|
-
if ini >= resultDict["TotalRecords"]:
|
|
750
|
-
return S_ERROR("Item number out of range")
|
|
751
|
-
if last > resultDict["TotalRecords"]:
|
|
752
|
-
last = resultDict["TotalRecords"]
|
|
753
|
-
|
|
754
|
-
selectedRows = allRows[ini:last]
|
|
755
|
-
resultDict["Records"] = []
|
|
756
|
-
for row in selectedRows:
|
|
757
|
-
resultDict["Records"].append(list(row.values()))
|
|
758
|
-
|
|
759
|
-
# Create the ParameterNames entry
|
|
760
|
-
resultDict["ParameterNames"] = list(selectedRows[0].keys())
|
|
761
|
-
# Find which element in the tuple contains the requested status
|
|
762
|
-
if statusColumn not in resultDict["ParameterNames"]:
|
|
763
|
-
return S_ERROR("Provided status column not present")
|
|
764
|
-
|
|
765
|
-
# Generate the status dictionary
|
|
766
|
-
statusDict = {}
|
|
767
|
-
for row in selectedRows:
|
|
768
|
-
status = row[statusColumn]
|
|
769
|
-
statusDict[status] = statusDict.setdefault(status, 0) + 1
|
|
770
|
-
resultDict["Extras"] = statusDict
|
|
771
|
-
|
|
772
|
-
# Obtain the distinct values of the selection parameters
|
|
773
|
-
res = self.transformationDB.getTableDistinctAttributeValues(
|
|
774
|
-
table, selectColumns, selectDict, older=toDate, newer=fromDate
|
|
775
|
-
)
|
|
776
|
-
distinctSelections = zip(selectColumns, [])
|
|
777
|
-
if res["OK"]:
|
|
778
|
-
distinctSelections = res["Value"]
|
|
779
|
-
resultDict["Selections"] = distinctSelections
|
|
780
|
-
|
|
781
|
-
return S_OK(resultDict)
|
|
782
|
-
|
|
783
|
-
types_getTransformationSummaryWeb = [dict, list, int, int]
|
|
784
|
-
|
|
785
|
-
def export_getTransformationSummaryWeb(self, selectDict, sortList, startItem, maxItems):
|
|
786
|
-
"""Get the summary of the transformation information for a given page in the generic format"""
|
|
787
|
-
|
|
788
|
-
# Obtain the timing information from the selectDict
|
|
789
|
-
last_update = selectDict.get("CreationDate", None)
|
|
790
|
-
if last_update:
|
|
791
|
-
del selectDict["CreationDate"]
|
|
792
|
-
fromDate = selectDict.get("FromDate", None)
|
|
793
|
-
if fromDate:
|
|
794
|
-
del selectDict["FromDate"]
|
|
795
|
-
if not fromDate:
|
|
796
|
-
fromDate = last_update
|
|
797
|
-
toDate = selectDict.get("ToDate", None)
|
|
798
|
-
if toDate:
|
|
799
|
-
del selectDict["ToDate"]
|
|
800
|
-
# Sorting instructions. Only one for the moment.
|
|
801
|
-
if sortList:
|
|
802
|
-
orderAttribute = []
|
|
803
|
-
for i in sortList:
|
|
804
|
-
orderAttribute += [i[0] + ":" + i[1]]
|
|
805
|
-
else:
|
|
806
|
-
orderAttribute = None
|
|
807
|
-
|
|
808
|
-
# Get the transformations that match the selection
|
|
809
|
-
res = self.transformationDB.getTransformations(
|
|
810
|
-
condDict=selectDict, older=toDate, newer=fromDate, orderAttribute=orderAttribute
|
|
811
|
-
)
|
|
812
|
-
if not res["OK"]:
|
|
813
|
-
return res
|
|
814
|
-
|
|
815
|
-
ops = Operations()
|
|
816
|
-
# Prepare the standard structure now within the resultDict dictionary
|
|
817
|
-
resultDict = {}
|
|
818
|
-
trList = res["Records"]
|
|
819
|
-
# Create the total records entry
|
|
820
|
-
nTrans = len(trList)
|
|
821
|
-
resultDict["TotalRecords"] = nTrans
|
|
822
|
-
# Create the ParameterNames entry
|
|
823
|
-
# As this list is a reference to the list in the DB, we cannot extend it, therefore copy it
|
|
824
|
-
resultDict["ParameterNames"] = list(res["ParameterNames"])
|
|
825
|
-
# Add the job states to the ParameterNames entry
|
|
826
|
-
taskStateNames = TASKS_STATE_NAMES + ops.getValue("Transformations/AdditionalTaskStates", [])
|
|
827
|
-
resultDict["ParameterNames"] += ["Jobs_" + x for x in taskStateNames]
|
|
828
|
-
# Add the file states to the ParameterNames entry
|
|
829
|
-
fileStateNames = FILES_STATE_NAMES + ops.getValue("Transformations/AdditionalFileStates", [])
|
|
830
|
-
resultDict["ParameterNames"] += ["Files_" + x for x in fileStateNames]
|
|
831
|
-
|
|
832
|
-
# Get the transformations which are within the selected window
|
|
833
|
-
if nTrans == 0:
|
|
834
|
-
return S_OK(resultDict)
|
|
835
|
-
ini = startItem
|
|
836
|
-
last = ini + maxItems
|
|
837
|
-
if ini >= nTrans:
|
|
838
|
-
return S_ERROR("Item number out of range")
|
|
839
|
-
if last > nTrans:
|
|
840
|
-
last = nTrans
|
|
841
|
-
transList = trList[ini:last]
|
|
842
|
-
|
|
843
|
-
statusDict = {}
|
|
844
|
-
extendableTranfs = ops.getValue("Transformations/ExtendableTransfTypes", ["Simulation", "MCsimulation"])
|
|
845
|
-
givenUpFileStatus = ops.getValue("Transformations/GivenUpFileStatus", ["MissingInFC"])
|
|
846
|
-
problematicStatuses = ops.getValue("Transformations/ProblematicStatuses", ["Problematic"])
|
|
847
|
-
# Add specific information for each selected transformation
|
|
848
|
-
for trans in transList:
|
|
849
|
-
transDict = dict(zip(resultDict["ParameterNames"], trans))
|
|
850
|
-
|
|
851
|
-
# Update the status counters
|
|
852
|
-
status = transDict["Status"]
|
|
853
|
-
statusDict[status] = statusDict.setdefault(status, 0) + 1
|
|
854
|
-
|
|
855
|
-
# Get the statistics on the number of jobs for the transformation
|
|
856
|
-
transID = transDict["TransformationID"]
|
|
857
|
-
res = self.transformationDB.getTransformationTaskStats(transID)
|
|
858
|
-
taskDict = {}
|
|
859
|
-
if res["OK"] and res["Value"]:
|
|
860
|
-
taskDict = res["Value"]
|
|
861
|
-
for state in taskStateNames:
|
|
862
|
-
trans.append(taskDict.get(state, 0))
|
|
863
|
-
|
|
864
|
-
# Get the statistics for the number of files for the transformation
|
|
865
|
-
fileDict = {}
|
|
866
|
-
transType = transDict["Type"]
|
|
867
|
-
if transType.lower() in extendableTranfs:
|
|
868
|
-
fileDict["PercentProcessed"] = "-"
|
|
869
|
-
else:
|
|
870
|
-
res = self.transformationDB.getTransformationStats(transID)
|
|
871
|
-
if res["OK"]:
|
|
872
|
-
fileDict = res["Value"]
|
|
873
|
-
total = fileDict["Total"]
|
|
874
|
-
for stat in givenUpFileStatus:
|
|
875
|
-
total -= fileDict.get(stat, 0)
|
|
876
|
-
processed = fileDict.get(TransformationFilesStatus.PROCESSED, 0)
|
|
877
|
-
fileDict["PercentProcessed"] = f"{int(processed * 1000.0 / total) / 10.0:.1f}" if total else 0.0
|
|
878
|
-
problematic = 0
|
|
879
|
-
for stat in problematicStatuses:
|
|
880
|
-
problematic += fileDict.get(stat, 0)
|
|
881
|
-
fileDict["Problematic"] = problematic
|
|
882
|
-
for state in fileStateNames:
|
|
883
|
-
trans.append(fileDict.get(state, 0))
|
|
884
|
-
|
|
885
|
-
resultDict["Records"] = transList
|
|
886
|
-
resultDict["Extras"] = statusDict
|
|
887
|
-
return S_OK(resultDict)
|
|
888
|
-
|
|
889
553
|
|
|
890
554
|
class TransformationManagerHandler(TransformationManagerHandlerMixin, RequestHandler):
|
|
891
555
|
pass
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Command Line Parameters for creating the Replication transformations Script
|
|
3
3
|
"""
|
|
4
|
-
from DIRAC import
|
|
4
|
+
from DIRAC import S_ERROR, S_OK, gLogger
|
|
5
|
+
from DIRAC.ConfigurationSystem.Client.Helpers.Registry import getVOForGroup
|
|
5
6
|
from DIRAC.Core.Security.Properties import SecurityProperty
|
|
6
7
|
from DIRAC.Core.Security.ProxyInfo import getProxyInfo
|
|
7
|
-
from DIRAC.ConfigurationSystem.Client.Helpers.Registry import getVOMSVOForGroup
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Params:
|
|
@@ -144,7 +144,7 @@ class Params:
|
|
|
144
144
|
return False
|
|
145
145
|
proxyValues = proxyInfo.get("Value", {})
|
|
146
146
|
group = proxyValues.get("group", "")
|
|
147
|
-
vomsvo =
|
|
147
|
+
vomsvo = getVOForGroup(group)
|
|
148
148
|
if not vomsvo:
|
|
149
149
|
self.errorMessages.append("ERROR: ProxyGroup not associated to VOMS VO, get a different proxy")
|
|
150
150
|
return False
|
|
@@ -16,7 +16,7 @@ from urllib.request import urlopen
|
|
|
16
16
|
from DIRAC.Interfaces.API.Dirac import Dirac
|
|
17
17
|
from DIRAC.Core.Utilities.File import mkDir
|
|
18
18
|
from DIRAC.Core.Base.Script import Script
|
|
19
|
-
from DIRAC.ConfigurationSystem.Client.Helpers.CSGlobals import getVO
|
|
19
|
+
from DIRAC.ConfigurationSystem.Client.Helpers.CSGlobals import getVO
|
|
20
20
|
from DIRAC.ConfigurationSystem.Client.ConfigurationData import gConfigurationData
|
|
21
21
|
|
|
22
22
|
|
|
@@ -79,14 +79,12 @@ def __configurePilot(basepath, vo):
|
|
|
79
79
|
This method was created specifically for LHCb pilots, more info
|
|
80
80
|
about othe VOs is needed to make it more general.
|
|
81
81
|
"""
|
|
82
|
-
currentSetup = getSetup()
|
|
83
82
|
masterCS = gConfigurationData.getMasterServer()
|
|
84
83
|
|
|
85
84
|
os.system(
|
|
86
85
|
"python "
|
|
87
86
|
+ basepath
|
|
88
|
-
+ "dirac-pilot.py -
|
|
89
|
-
% (currentSetup, vo, masterCS)
|
|
87
|
+
+ f"dirac-pilot.py -l {vo} -C {masterCS} -N ce.debug.ch -Q default -n DIRAC.JobDebugger.ch -dd"
|
|
90
88
|
)
|
|
91
89
|
|
|
92
90
|
diracdir = os.path.expanduser("~") + os.path.sep
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"""Test the dirac-transformation-replication script and helper"""
|
|
2
2
|
import unittest
|
|
3
|
+
from unittest.mock import MagicMock as Mock
|
|
4
|
+
from unittest.mock import patch
|
|
3
5
|
|
|
4
|
-
from
|
|
5
|
-
|
|
6
|
-
from DIRAC import S_OK, S_ERROR
|
|
7
|
-
|
|
8
|
-
from DIRAC.TransformationSystem.Utilities.ReplicationTransformation import createDataTransformation
|
|
6
|
+
from DIRAC import S_ERROR, S_OK
|
|
9
7
|
from DIRAC.TransformationSystem.Utilities.ReplicationCLIParameters import Params
|
|
8
|
+
from DIRAC.TransformationSystem.Utilities.ReplicationTransformation import createDataTransformation
|
|
10
9
|
|
|
11
|
-
GET_VOMS = "DIRAC.TransformationSystem.Utilities.ReplicationCLIParameters.
|
|
10
|
+
GET_VOMS = "DIRAC.TransformationSystem.Utilities.ReplicationCLIParameters.getVOForGroup"
|
|
12
11
|
GET_PROXY = "DIRAC.TransformationSystem.Utilities.ReplicationCLIParameters.getProxyInfo"
|
|
13
12
|
|
|
14
13
|
|
|
@@ -5,6 +5,8 @@ import os
|
|
|
5
5
|
import copy
|
|
6
6
|
import shutil
|
|
7
7
|
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
8
10
|
from unittest.mock import MagicMock as Mock
|
|
9
11
|
|
|
10
12
|
from DIRAC import gLogger
|
|
@@ -742,6 +744,7 @@ class FailoverRequestSuccess(ModulesTestCase):
|
|
|
742
744
|
class ScriptSuccess(ModulesTestCase):
|
|
743
745
|
#################################################
|
|
744
746
|
|
|
747
|
+
@pytest.mark.slow
|
|
745
748
|
def test_execute(self):
|
|
746
749
|
self.script.jobType = "merge"
|
|
747
750
|
self.script.stepInputData = ["foo", "bar"]
|
|
@@ -770,6 +773,7 @@ class ScriptSuccess(ModulesTestCase):
|
|
|
770
773
|
class ScriptUnicode(ModulesTestCase):
|
|
771
774
|
#################################################
|
|
772
775
|
|
|
776
|
+
@pytest.mark.slow
|
|
773
777
|
def test_execute(self):
|
|
774
778
|
self.script.jobType = "merge"
|
|
775
779
|
self.script.stepInputData = ["foo", "bar"]
|
|
@@ -799,6 +803,7 @@ class ScriptUnicode(ModulesTestCase):
|
|
|
799
803
|
class ScriptFailure(ModulesTestCase):
|
|
800
804
|
#################################################
|
|
801
805
|
|
|
806
|
+
@pytest.mark.slow
|
|
802
807
|
def test_execute(self):
|
|
803
808
|
self.script.jobType = "merge"
|
|
804
809
|
self.script.stepInputData = ["foo", "bar"]
|
|
@@ -236,7 +236,6 @@ class JobAgent(AgentModule):
|
|
|
236
236
|
jobGroup = matcherInfo["Group"]
|
|
237
237
|
owner = matcherInfo["Owner"]
|
|
238
238
|
ceDict = matcherInfo["CEDict"]
|
|
239
|
-
matchTime = matcherInfo["matchTime"]
|
|
240
239
|
|
|
241
240
|
optimizerParams = {}
|
|
242
241
|
for key in matcherInfo:
|
|
@@ -263,9 +262,6 @@ class JobAgent(AgentModule):
|
|
|
263
262
|
self.log.verbose("Job request successful: \n", jobRequest["Value"])
|
|
264
263
|
self.log.info("Received", f"JobID={jobID}, JobType={jobType}, Owner={owner}, JobGroup={jobGroup}")
|
|
265
264
|
self.jobCount += 1
|
|
266
|
-
self.jobs[jobID]["JobReport"].setJobParameter(
|
|
267
|
-
par_name="MatcherServiceTime", par_value=str(matchTime), sendFlag=False
|
|
268
|
-
)
|
|
269
265
|
|
|
270
266
|
self.jobs[jobID]["JobReport"].setJobStatus(minorStatus="Job Received by Agent", sendFlag=False)
|
|
271
267
|
result_setupProxy = self._setupProxy(owner, jobGroup)
|
|
@@ -547,7 +543,7 @@ class JobAgent(AgentModule):
|
|
|
547
543
|
jobRequest = MatcherClient().requestJob(ceDict)
|
|
548
544
|
matchTime = time.time() - start
|
|
549
545
|
|
|
550
|
-
self.log.
|
|
546
|
+
self.log.verbose("MatcherTime", f"= {matchTime:.2f} (s)")
|
|
551
547
|
if jobRequest["OK"]:
|
|
552
548
|
jobRequest["Value"]["matchTime"] = matchTime
|
|
553
549
|
jobRequest["Value"]["CEDict"] = ceDict
|
|
@@ -35,10 +35,12 @@ from DIRAC.RequestManagementSystem.Client.Operation import Operation
|
|
|
35
35
|
from DIRAC.RequestManagementSystem.Client.ReqClient import ReqClient
|
|
36
36
|
from DIRAC.RequestManagementSystem.Client.Request import Request
|
|
37
37
|
from DIRAC.WorkloadManagementSystem.Client import JobStatus
|
|
38
|
-
from DIRAC.WorkloadManagementSystem.Client.JobMonitoringClient import JobMonitoringClient
|
|
39
|
-
from DIRAC.WorkloadManagementSystem.Client.SandboxStoreClient import SandboxStoreClient
|
|
40
38
|
from DIRAC.WorkloadManagementSystem.Client.WMSClient import WMSClient
|
|
41
39
|
from DIRAC.WorkloadManagementSystem.DB.JobDB import JobDB
|
|
40
|
+
from DIRAC.WorkloadManagementSystem.DB.SandboxMetadataDB import SandboxMetadataDB
|
|
41
|
+
from DIRAC.WorkloadManagementSystem.Service.JobPolicy import RIGHT_DELETE
|
|
42
|
+
from DIRAC.WorkloadManagementSystem.DB.StatusUtils import kill_delete_jobs
|
|
43
|
+
from DIRAC.WorkloadManagementSystem.Utilities.JobParameters import getJobParameters
|
|
42
44
|
|
|
43
45
|
|
|
44
46
|
class JobCleaningAgent(AgentModule):
|
|
@@ -152,8 +154,9 @@ class JobCleaningAgent(AgentModule):
|
|
|
152
154
|
return S_OK()
|
|
153
155
|
|
|
154
156
|
self.log.info("Unassigning sandboxes from soon to be deleted jobs", f"({len(jobList)})")
|
|
155
|
-
|
|
156
|
-
|
|
157
|
+
|
|
158
|
+
entitiesList = [f"Job:{jobId}" for jobId in jobList]
|
|
159
|
+
if not (result := SandboxMetadataDB().unassignEntities(entitiesList))["OK"]:
|
|
157
160
|
self.log.error("Cannot unassign jobs to sandboxes", result["Message"])
|
|
158
161
|
return result
|
|
159
162
|
|
|
@@ -229,11 +232,11 @@ class JobCleaningAgent(AgentModule):
|
|
|
229
232
|
if not res["OK"]:
|
|
230
233
|
self.log.error("No DN found", f"for {user}")
|
|
231
234
|
return res
|
|
232
|
-
wmsClient = WMSClient(useCertificates=True, delegatedDN=res["Value"][0], delegatedGroup=ownerGroup)
|
|
233
235
|
if remove:
|
|
236
|
+
wmsClient = WMSClient(useCertificates=True, delegatedDN=res["Value"][0], delegatedGroup=ownerGroup)
|
|
234
237
|
result = wmsClient.removeJob(jobsList)
|
|
235
238
|
else:
|
|
236
|
-
result =
|
|
239
|
+
result = kill_delete_jobs(RIGHT_DELETE, jobsList)
|
|
237
240
|
if not result["OK"]:
|
|
238
241
|
self.log.error(
|
|
239
242
|
f"Could not {'remove' if remove else 'delete'} jobs",
|
|
@@ -293,7 +296,8 @@ class JobCleaningAgent(AgentModule):
|
|
|
293
296
|
failed = {}
|
|
294
297
|
successful = {}
|
|
295
298
|
|
|
296
|
-
|
|
299
|
+
jobIDs = [int(jobID) for jobID in jobIDList]
|
|
300
|
+
result = getJobParameters(jobIDs, "OutputSandboxLFN")
|
|
297
301
|
if not result["OK"]:
|
|
298
302
|
return result
|
|
299
303
|
osLFNDict = result["Value"]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""This agent syncs CS and pilot files to a web server of your choice
|
|
2
2
|
|
|
3
3
|
.. literalinclude:: ../ConfigTemplate.cfg
|
|
4
4
|
:start-after: ##BEGIN PilotSyncAgent
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
:caption: PilotsSyncAgent options
|
|
8
8
|
|
|
9
9
|
"""
|
|
10
|
+
|
|
10
11
|
import os
|
|
11
12
|
import json
|
|
12
13
|
import shutil
|
|
@@ -38,8 +39,8 @@ class PilotSyncAgent(AgentModule):
|
|
|
38
39
|
self.workingDirectory = self.am_getOption("WorkDirectory")
|
|
39
40
|
self.saveDir = self.am_getOption("SaveDirectory", self.saveDir)
|
|
40
41
|
self.uploadLocations = self.am_getOption("UploadLocations", self.uploadLocations)
|
|
41
|
-
includeMasterCS = self.am_getOption("IncludeMasterCS", self.includeMasterCS)
|
|
42
|
-
if isinstance(includeMasterCS, str) and includeMasterCS.lower() in ["n", "no", "false"]:
|
|
42
|
+
self.includeMasterCS = self.am_getOption("IncludeMasterCS", self.includeMasterCS)
|
|
43
|
+
if isinstance(self.includeMasterCS, str) and self.includeMasterCS.lower() in ["n", "no", "false"]:
|
|
43
44
|
self.includeMasterCS = False
|
|
44
45
|
|
|
45
46
|
self.certAndKeyLocation = getHostCertificateAndKeyLocation()
|