wmglobalqueue 2.3.10__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.
Potentially problematic release.
This version of wmglobalqueue might be problematic. Click here for more details.
- Utils/CPMetrics.py +270 -0
- Utils/CertTools.py +62 -0
- Utils/EmailAlert.py +50 -0
- Utils/ExtendedUnitTestCase.py +62 -0
- Utils/FileTools.py +182 -0
- Utils/IteratorTools.py +80 -0
- Utils/MathUtils.py +31 -0
- Utils/MemoryCache.py +119 -0
- Utils/Patterns.py +24 -0
- Utils/Pipeline.py +137 -0
- Utils/PortForward.py +97 -0
- Utils/ProcessStats.py +103 -0
- Utils/PythonVersion.py +17 -0
- Utils/Signals.py +36 -0
- Utils/TemporaryEnvironment.py +27 -0
- Utils/Throttled.py +227 -0
- Utils/Timers.py +130 -0
- Utils/Timestamps.py +86 -0
- Utils/TokenManager.py +143 -0
- Utils/Tracing.py +60 -0
- Utils/TwPrint.py +98 -0
- Utils/Utilities.py +308 -0
- Utils/__init__.py +11 -0
- WMCore/ACDC/Collection.py +57 -0
- WMCore/ACDC/CollectionTypes.py +12 -0
- WMCore/ACDC/CouchCollection.py +67 -0
- WMCore/ACDC/CouchFileset.py +238 -0
- WMCore/ACDC/CouchService.py +73 -0
- WMCore/ACDC/DataCollectionService.py +485 -0
- WMCore/ACDC/Fileset.py +94 -0
- WMCore/ACDC/__init__.py +11 -0
- WMCore/Algorithms/Alarm.py +39 -0
- WMCore/Algorithms/MathAlgos.py +274 -0
- WMCore/Algorithms/MiscAlgos.py +67 -0
- WMCore/Algorithms/ParseXMLFile.py +115 -0
- WMCore/Algorithms/Permissions.py +27 -0
- WMCore/Algorithms/Singleton.py +58 -0
- WMCore/Algorithms/SubprocessAlgos.py +129 -0
- WMCore/Algorithms/__init__.py +7 -0
- WMCore/Cache/GenericDataCache.py +98 -0
- WMCore/Cache/WMConfigCache.py +572 -0
- WMCore/Cache/__init__.py +0 -0
- WMCore/Configuration.py +651 -0
- WMCore/DAOFactory.py +47 -0
- WMCore/DataStructs/File.py +177 -0
- WMCore/DataStructs/Fileset.py +140 -0
- WMCore/DataStructs/Job.py +182 -0
- WMCore/DataStructs/JobGroup.py +142 -0
- WMCore/DataStructs/JobPackage.py +49 -0
- WMCore/DataStructs/LumiList.py +734 -0
- WMCore/DataStructs/Mask.py +219 -0
- WMCore/DataStructs/MathStructs/ContinuousSummaryHistogram.py +197 -0
- WMCore/DataStructs/MathStructs/DiscreteSummaryHistogram.py +92 -0
- WMCore/DataStructs/MathStructs/SummaryHistogram.py +117 -0
- WMCore/DataStructs/MathStructs/__init__.py +0 -0
- WMCore/DataStructs/Pickleable.py +24 -0
- WMCore/DataStructs/Run.py +256 -0
- WMCore/DataStructs/Subscription.py +175 -0
- WMCore/DataStructs/WMObject.py +47 -0
- WMCore/DataStructs/WorkUnit.py +112 -0
- WMCore/DataStructs/Workflow.py +60 -0
- WMCore/DataStructs/__init__.py +8 -0
- WMCore/Database/CMSCouch.py +1349 -0
- WMCore/Database/ConfigDBMap.py +29 -0
- WMCore/Database/CouchUtils.py +118 -0
- WMCore/Database/DBCore.py +198 -0
- WMCore/Database/DBCreator.py +113 -0
- WMCore/Database/DBExceptionHandler.py +57 -0
- WMCore/Database/DBFactory.py +110 -0
- WMCore/Database/DBFormatter.py +177 -0
- WMCore/Database/Dialects.py +13 -0
- WMCore/Database/ExecuteDAO.py +327 -0
- WMCore/Database/MongoDB.py +241 -0
- WMCore/Database/MySQL/Destroy.py +42 -0
- WMCore/Database/MySQL/ListUserContent.py +20 -0
- WMCore/Database/MySQL/__init__.py +9 -0
- WMCore/Database/MySQLCore.py +132 -0
- WMCore/Database/Oracle/Destroy.py +56 -0
- WMCore/Database/Oracle/ListUserContent.py +19 -0
- WMCore/Database/Oracle/__init__.py +9 -0
- WMCore/Database/ResultSet.py +44 -0
- WMCore/Database/Transaction.py +91 -0
- WMCore/Database/__init__.py +9 -0
- WMCore/Database/ipy_profile_couch.py +438 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/CleanUpTask.py +29 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/HeartbeatMonitor.py +105 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/LocationUpdateTask.py +28 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/ReqMgrInteractionTask.py +35 -0
- WMCore/GlobalWorkQueue/CherryPyThreads/__init__.py +0 -0
- WMCore/GlobalWorkQueue/__init__.py +0 -0
- WMCore/GroupUser/CouchObject.py +127 -0
- WMCore/GroupUser/Decorators.py +51 -0
- WMCore/GroupUser/Group.py +33 -0
- WMCore/GroupUser/Interface.py +73 -0
- WMCore/GroupUser/User.py +96 -0
- WMCore/GroupUser/__init__.py +11 -0
- WMCore/Lexicon.py +836 -0
- WMCore/REST/Auth.py +202 -0
- WMCore/REST/CherryPyPeriodicTask.py +166 -0
- WMCore/REST/Error.py +333 -0
- WMCore/REST/Format.py +642 -0
- WMCore/REST/HeartbeatMonitorBase.py +90 -0
- WMCore/REST/Main.py +623 -0
- WMCore/REST/Server.py +2435 -0
- WMCore/REST/Services.py +24 -0
- WMCore/REST/Test.py +120 -0
- WMCore/REST/Tools.py +38 -0
- WMCore/REST/Validation.py +250 -0
- WMCore/REST/__init__.py +1 -0
- WMCore/ReqMgr/DataStructs/RequestStatus.py +209 -0
- WMCore/ReqMgr/DataStructs/RequestType.py +13 -0
- WMCore/ReqMgr/DataStructs/__init__.py +0 -0
- WMCore/ReqMgr/__init__.py +1 -0
- WMCore/Services/AlertManager/AlertManagerAPI.py +111 -0
- WMCore/Services/AlertManager/__init__.py +0 -0
- WMCore/Services/CRIC/CRIC.py +238 -0
- WMCore/Services/CRIC/__init__.py +0 -0
- WMCore/Services/DBS/DBS3Reader.py +1044 -0
- WMCore/Services/DBS/DBSConcurrency.py +44 -0
- WMCore/Services/DBS/DBSErrors.py +113 -0
- WMCore/Services/DBS/DBSReader.py +23 -0
- WMCore/Services/DBS/DBSUtils.py +139 -0
- WMCore/Services/DBS/DBSWriterObjects.py +381 -0
- WMCore/Services/DBS/ProdException.py +133 -0
- WMCore/Services/DBS/__init__.py +8 -0
- WMCore/Services/FWJRDB/FWJRDBAPI.py +118 -0
- WMCore/Services/FWJRDB/__init__.py +0 -0
- WMCore/Services/HTTPS/HTTPSAuthHandler.py +66 -0
- WMCore/Services/HTTPS/__init__.py +0 -0
- WMCore/Services/LogDB/LogDB.py +201 -0
- WMCore/Services/LogDB/LogDBBackend.py +191 -0
- WMCore/Services/LogDB/LogDBExceptions.py +11 -0
- WMCore/Services/LogDB/LogDBReport.py +85 -0
- WMCore/Services/LogDB/__init__.py +0 -0
- WMCore/Services/MSPileup/__init__.py +0 -0
- WMCore/Services/MSUtils/MSUtils.py +54 -0
- WMCore/Services/MSUtils/__init__.py +0 -0
- WMCore/Services/McM/McM.py +173 -0
- WMCore/Services/McM/__init__.py +8 -0
- WMCore/Services/MonIT/Grafana.py +133 -0
- WMCore/Services/MonIT/__init__.py +0 -0
- WMCore/Services/PyCondor/PyCondorAPI.py +154 -0
- WMCore/Services/PyCondor/PyCondorUtils.py +105 -0
- WMCore/Services/PyCondor/__init__.py +0 -0
- WMCore/Services/ReqMgr/ReqMgr.py +261 -0
- WMCore/Services/ReqMgr/__init__.py +0 -0
- WMCore/Services/ReqMgrAux/ReqMgrAux.py +419 -0
- WMCore/Services/ReqMgrAux/__init__.py +0 -0
- WMCore/Services/RequestDB/RequestDBReader.py +267 -0
- WMCore/Services/RequestDB/RequestDBWriter.py +39 -0
- WMCore/Services/RequestDB/__init__.py +0 -0
- WMCore/Services/Requests.py +624 -0
- WMCore/Services/Rucio/Rucio.py +1287 -0
- WMCore/Services/Rucio/RucioUtils.py +74 -0
- WMCore/Services/Rucio/__init__.py +0 -0
- WMCore/Services/RucioConMon/RucioConMon.py +128 -0
- WMCore/Services/RucioConMon/__init__.py +0 -0
- WMCore/Services/Service.py +400 -0
- WMCore/Services/StompAMQ/__init__.py +0 -0
- WMCore/Services/TagCollector/TagCollector.py +155 -0
- WMCore/Services/TagCollector/XMLUtils.py +98 -0
- WMCore/Services/TagCollector/__init__.py +0 -0
- WMCore/Services/UUIDLib.py +13 -0
- WMCore/Services/UserFileCache/UserFileCache.py +160 -0
- WMCore/Services/UserFileCache/__init__.py +8 -0
- WMCore/Services/WMAgent/WMAgent.py +63 -0
- WMCore/Services/WMAgent/__init__.py +0 -0
- WMCore/Services/WMArchive/CMSSWMetrics.py +526 -0
- WMCore/Services/WMArchive/DataMap.py +463 -0
- WMCore/Services/WMArchive/WMArchive.py +33 -0
- WMCore/Services/WMArchive/__init__.py +0 -0
- WMCore/Services/WMBS/WMBS.py +97 -0
- WMCore/Services/WMBS/__init__.py +0 -0
- WMCore/Services/WMStats/DataStruct/RequestInfoCollection.py +300 -0
- WMCore/Services/WMStats/DataStruct/__init__.py +0 -0
- WMCore/Services/WMStats/WMStatsPycurl.py +145 -0
- WMCore/Services/WMStats/WMStatsReader.py +445 -0
- WMCore/Services/WMStats/WMStatsWriter.py +273 -0
- WMCore/Services/WMStats/__init__.py +0 -0
- WMCore/Services/WMStatsServer/WMStatsServer.py +134 -0
- WMCore/Services/WMStatsServer/__init__.py +0 -0
- WMCore/Services/WorkQueue/WorkQueue.py +492 -0
- WMCore/Services/WorkQueue/__init__.py +0 -0
- WMCore/Services/__init__.py +8 -0
- WMCore/Services/pycurl_manager.py +574 -0
- WMCore/WMBase.py +50 -0
- WMCore/WMConnectionBase.py +164 -0
- WMCore/WMException.py +183 -0
- WMCore/WMExceptions.py +269 -0
- WMCore/WMFactory.py +76 -0
- WMCore/WMInit.py +228 -0
- WMCore/WMLogging.py +108 -0
- WMCore/WMSpec/ConfigSectionTree.py +442 -0
- WMCore/WMSpec/Persistency.py +135 -0
- WMCore/WMSpec/Steps/BuildMaster.py +87 -0
- WMCore/WMSpec/Steps/BuildTools.py +201 -0
- WMCore/WMSpec/Steps/Builder.py +97 -0
- WMCore/WMSpec/Steps/Diagnostic.py +89 -0
- WMCore/WMSpec/Steps/Emulator.py +62 -0
- WMCore/WMSpec/Steps/ExecuteMaster.py +208 -0
- WMCore/WMSpec/Steps/Executor.py +210 -0
- WMCore/WMSpec/Steps/StepFactory.py +213 -0
- WMCore/WMSpec/Steps/TaskEmulator.py +75 -0
- WMCore/WMSpec/Steps/Template.py +204 -0
- WMCore/WMSpec/Steps/Templates/AlcaHarvest.py +76 -0
- WMCore/WMSpec/Steps/Templates/CMSSW.py +613 -0
- WMCore/WMSpec/Steps/Templates/DQMUpload.py +59 -0
- WMCore/WMSpec/Steps/Templates/DeleteFiles.py +70 -0
- WMCore/WMSpec/Steps/Templates/LogArchive.py +84 -0
- WMCore/WMSpec/Steps/Templates/LogCollect.py +105 -0
- WMCore/WMSpec/Steps/Templates/StageOut.py +105 -0
- WMCore/WMSpec/Steps/Templates/__init__.py +10 -0
- WMCore/WMSpec/Steps/WMExecutionFailure.py +21 -0
- WMCore/WMSpec/Steps/__init__.py +8 -0
- WMCore/WMSpec/Utilities.py +63 -0
- WMCore/WMSpec/WMSpecErrors.py +12 -0
- WMCore/WMSpec/WMStep.py +347 -0
- WMCore/WMSpec/WMTask.py +1980 -0
- WMCore/WMSpec/WMWorkload.py +2288 -0
- WMCore/WMSpec/WMWorkloadTools.py +370 -0
- WMCore/WMSpec/__init__.py +9 -0
- WMCore/WorkQueue/DataLocationMapper.py +273 -0
- WMCore/WorkQueue/DataStructs/ACDCBlock.py +47 -0
- WMCore/WorkQueue/DataStructs/Block.py +48 -0
- WMCore/WorkQueue/DataStructs/CouchWorkQueueElement.py +148 -0
- WMCore/WorkQueue/DataStructs/WorkQueueElement.py +274 -0
- WMCore/WorkQueue/DataStructs/WorkQueueElementResult.py +152 -0
- WMCore/WorkQueue/DataStructs/WorkQueueElementsSummary.py +185 -0
- WMCore/WorkQueue/DataStructs/__init__.py +0 -0
- WMCore/WorkQueue/Policy/End/EndPolicyInterface.py +44 -0
- WMCore/WorkQueue/Policy/End/SingleShot.py +22 -0
- WMCore/WorkQueue/Policy/End/__init__.py +32 -0
- WMCore/WorkQueue/Policy/PolicyInterface.py +17 -0
- WMCore/WorkQueue/Policy/Start/Block.py +258 -0
- WMCore/WorkQueue/Policy/Start/Dataset.py +180 -0
- WMCore/WorkQueue/Policy/Start/MonteCarlo.py +131 -0
- WMCore/WorkQueue/Policy/Start/ResubmitBlock.py +171 -0
- WMCore/WorkQueue/Policy/Start/StartPolicyInterface.py +316 -0
- WMCore/WorkQueue/Policy/Start/__init__.py +34 -0
- WMCore/WorkQueue/Policy/__init__.py +57 -0
- WMCore/WorkQueue/WMBSHelper.py +772 -0
- WMCore/WorkQueue/WorkQueue.py +1237 -0
- WMCore/WorkQueue/WorkQueueBackend.py +750 -0
- WMCore/WorkQueue/WorkQueueBase.py +39 -0
- WMCore/WorkQueue/WorkQueueExceptions.py +44 -0
- WMCore/WorkQueue/WorkQueueReqMgrInterface.py +278 -0
- WMCore/WorkQueue/WorkQueueUtils.py +130 -0
- WMCore/WorkQueue/__init__.py +13 -0
- WMCore/Wrappers/JsonWrapper/JSONThunker.py +342 -0
- WMCore/Wrappers/JsonWrapper/__init__.py +7 -0
- WMCore/Wrappers/__init__.py +6 -0
- WMCore/__init__.py +10 -0
- wmglobalqueue-2.3.10.data/data/bin/wmc-dist-patch +15 -0
- wmglobalqueue-2.3.10.data/data/bin/wmc-dist-unpatch +8 -0
- wmglobalqueue-2.3.10.data/data/bin/wmc-httpd +3 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/.couchapprc +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/README.md +40 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/_attachments/index.html +264 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/_attachments/js/ElementInfoByWorkflow.js +96 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/_attachments/js/StuckElementInfo.js +57 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/_attachments/js/WorkloadInfoTable.js +80 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/_attachments/js/dataTable.js +70 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/_attachments/js/namespace.js +23 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/_attachments/style/main.css +75 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/couchapp.json +4 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/filters/childQueueFilter.js +13 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/filters/filterDeletedDocs.js +3 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/filters/queueFilter.js +11 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/language +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/lib/mustache.js +333 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/lib/validate.js +27 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/lib/workqueue_utils.js +61 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/lists/elementsDetail.js +28 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/lists/filter.js +86 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/lists/stuckElements.js +38 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/lists/workRestrictions.js +153 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/lists/workflowSummary.js +28 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/rewrites.json +73 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/shows/redirect.js +23 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/shows/status.js +40 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/templates/ElementSummaryByWorkflow.html +27 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/templates/StuckElementSummary.html +26 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/templates/TaskStatus.html +23 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/templates/WorkflowSummary.html +27 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/templates/partials/workqueue-common-lib.html +2 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib-remote.html +16 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib.html +18 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/updates/in-place.js +50 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/validate_doc_update.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.couch.app.js +235 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.pathbinder.js +173 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/activeData/map.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/activeData/reduce.js +2 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/activeParentData/map.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/activeParentData/reduce.js +2 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/activePileupData/map.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/activePileupData/reduce.js +2 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/analyticsData/map.js +11 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/analyticsData/reduce.js +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/availableByPriority/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/conflicts/map.js +5 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elements/map.js +5 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elementsByData/map.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elementsByParent/map.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elementsByParentData/map.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elementsByPileupData/map.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elementsByStatus/map.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elementsBySubscription/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/map.js +8 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/reduce.js +3 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/elementsDetailByWorkflowAndStatus/map.js +26 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/map.js +10 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/reduce.js +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/reduce.js +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/reduce.js +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/reduce.js +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByRequest/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByRequest/reduce.js +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByStatus/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByStatus/reduce.js +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/reduce.js +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/openRequests/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/recent-items/map.js +5 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/reduce.js +1 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/specsByWorkflow/map.js +5 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/stuckElements/map.js +38 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/map.js +12 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/reduce.js +3 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/wmbsUrl/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/wmbsUrl/reduce.js +2 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/map.js +6 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/reduce.js +2 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/workflowSummary/map.js +9 -0
- wmglobalqueue-2.3.10.data/data/data/couchapps/WorkQueue/views/workflowSummary/reduce.js +10 -0
- wmglobalqueue-2.3.10.dist-info/LICENSE +202 -0
- wmglobalqueue-2.3.10.dist-info/METADATA +24 -0
- wmglobalqueue-2.3.10.dist-info/NOTICE +16 -0
- wmglobalqueue-2.3.10.dist-info/RECORD +345 -0
- wmglobalqueue-2.3.10.dist-info/WHEEL +5 -0
- wmglobalqueue-2.3.10.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WorkQueueElementsSummary
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import (print_function, division)
|
|
6
|
+
|
|
7
|
+
from builtins import str, bytes, object
|
|
8
|
+
from future.utils import viewitems
|
|
9
|
+
|
|
10
|
+
from collections import defaultdict
|
|
11
|
+
from math import ceil
|
|
12
|
+
|
|
13
|
+
from WMCore.WorkQueue.DataStructs.WorkQueueElement import possibleSites
|
|
14
|
+
from WMCore.WorkQueue.DataStructs.WorkQueueElementResult import WorkQueueElementResult
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def getGlobalSiteStatusSummary(elements, status=None, dataLocality=False):
|
|
18
|
+
"""
|
|
19
|
+
_getGlobalSiteStatusSummary_
|
|
20
|
+
|
|
21
|
+
Given a dict with workqueue elements keyed by status, such as this format:
|
|
22
|
+
{u'Canceled': [{u'Inputs': {}, u'Jobs': 18,...}, {u'Jobs': 11,...}],
|
|
23
|
+
u'Running': [{'Priority': 190000,..}, ...]}
|
|
24
|
+
|
|
25
|
+
Creates a summary of jobs and number of wq elements in each status
|
|
26
|
+
distributed among the sites whitelisted. There are 2 job distribution:
|
|
27
|
+
*) unique top level jobs per site and per status and (equally
|
|
28
|
+
distributed among all sites)
|
|
29
|
+
*) possible top level jobs per site and per status (consider all
|
|
30
|
+
jobs can run in a single location)
|
|
31
|
+
|
|
32
|
+
If status is provided, then skip any workqueue element not in the
|
|
33
|
+
given status. Otherwise filter only active workqueue status.
|
|
34
|
+
|
|
35
|
+
If dataLocality is set to True, then it considers only sites that pass
|
|
36
|
+
the data location constraint.
|
|
37
|
+
"""
|
|
38
|
+
if status and isinstance(status, (str, bytes)):
|
|
39
|
+
activeStatus = [status]
|
|
40
|
+
elif status and isinstance(status, (list, tuple)):
|
|
41
|
+
activeStatus = status
|
|
42
|
+
else:
|
|
43
|
+
activeStatus = list(elements)
|
|
44
|
+
|
|
45
|
+
uniqueJobsSummary = {}
|
|
46
|
+
possibleJobsSummary = {}
|
|
47
|
+
|
|
48
|
+
for st in activeStatus:
|
|
49
|
+
uniqueJobsSummary.setdefault(st, {})
|
|
50
|
+
possibleJobsSummary.setdefault(st, {})
|
|
51
|
+
uniqueJobs = {}
|
|
52
|
+
possibleJobs = {}
|
|
53
|
+
for elem in elements.get(st, []):
|
|
54
|
+
elem = elem['WMCore.WorkQueue.DataStructs.WorkQueueElement.WorkQueueElement']
|
|
55
|
+
if dataLocality:
|
|
56
|
+
commonSites = possibleSites(elem)
|
|
57
|
+
else:
|
|
58
|
+
commonSites = list(set(elem['SiteWhitelist']) - set(elem['SiteBlacklist']))
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
jobsPerSite = elem['Jobs'] / len(commonSites)
|
|
62
|
+
except ZeroDivisionError:
|
|
63
|
+
commonSites = ['NoPossibleSite']
|
|
64
|
+
jobsPerSite = elem['Jobs']
|
|
65
|
+
|
|
66
|
+
for site in commonSites:
|
|
67
|
+
uniqueJobs.setdefault(site, {'sum_jobs': 0, 'num_elem': 0})
|
|
68
|
+
possibleJobs.setdefault(site, {'sum_jobs': 0, 'num_elem': 0})
|
|
69
|
+
|
|
70
|
+
uniqueJobs[site]['sum_jobs'] += ceil(jobsPerSite)
|
|
71
|
+
uniqueJobs[site]['num_elem'] += 1
|
|
72
|
+
possibleJobs[site]['sum_jobs'] += ceil(elem['Jobs'])
|
|
73
|
+
possibleJobs[site]['num_elem'] += 1
|
|
74
|
+
|
|
75
|
+
uniqueJobsSummary[st].update(uniqueJobs)
|
|
76
|
+
possibleJobsSummary[st].update(possibleJobs)
|
|
77
|
+
|
|
78
|
+
return uniqueJobsSummary, possibleJobsSummary
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class WorkQueueElementsSummary(object):
|
|
82
|
+
"""Class to hold the status of a related group of WorkQueueElements"""
|
|
83
|
+
def __init__(self, elements):
|
|
84
|
+
self.elements = elements
|
|
85
|
+
|
|
86
|
+
elementsByRequest = {}
|
|
87
|
+
for ele in elements:
|
|
88
|
+
elementsByRequest.setdefault(ele["RequestName"], [])
|
|
89
|
+
elementsByRequest[ele["RequestName"]].append(ele)
|
|
90
|
+
|
|
91
|
+
self.wqResultsByRequest = {}
|
|
92
|
+
for reqName, wqElements in viewitems(elementsByRequest):
|
|
93
|
+
self.wqResultsByRequest[reqName] = WorkQueueElementResult(Elements=wqElements)
|
|
94
|
+
|
|
95
|
+
def elementsWithHigherPriorityInSameSites(self, requestName, returnFormat="dict"):
|
|
96
|
+
|
|
97
|
+
if requestName not in self.wqResultsByRequest:
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
priority = self.wqResultsByRequest[requestName]['Priority']
|
|
101
|
+
creationTime = self.wqResultsByRequest[requestName]['Elements'][0]['CreationTime']
|
|
102
|
+
|
|
103
|
+
sites = self.getPossibleSitesByRequest(requestName)
|
|
104
|
+
|
|
105
|
+
sortedElements = []
|
|
106
|
+
for reqName in self.wqResultsByRequest:
|
|
107
|
+
# skip the workflow
|
|
108
|
+
if reqName == requestName:
|
|
109
|
+
continue
|
|
110
|
+
if self.wqResultsByRequest[reqName]['Priority'] >= priority:
|
|
111
|
+
for element in self.wqResultsByRequest[reqName]['Elements']:
|
|
112
|
+
if element['CreationTime'] > creationTime:
|
|
113
|
+
continue
|
|
114
|
+
if len(sites) > 0:
|
|
115
|
+
commonSites = possibleSites(element)
|
|
116
|
+
if len(set(commonSites) & sites) > 0:
|
|
117
|
+
sortedElements.append(element)
|
|
118
|
+
else:
|
|
119
|
+
sortedElements.append(element)
|
|
120
|
+
# sort elements to get them in priority first and timestamp order
|
|
121
|
+
sortedElements.sort(key=lambda element: element['CreationTime'])
|
|
122
|
+
sortedElements.sort(key = lambda x: x['Priority'], reverse = True)
|
|
123
|
+
if returnFormat == "list":
|
|
124
|
+
return sortedElements
|
|
125
|
+
elif returnFormat == "dict":
|
|
126
|
+
sortedByRequest = defaultdict(list)
|
|
127
|
+
for ele in sortedElements:
|
|
128
|
+
sortedByRequest[ele['RequestName']].append(ele)
|
|
129
|
+
|
|
130
|
+
for request in sortedByRequest:
|
|
131
|
+
sortedByRequest[request] = WorkQueueElementResult(Elements=sortedByRequest[request])
|
|
132
|
+
return sortedByRequest
|
|
133
|
+
|
|
134
|
+
def getPossibleSitesByRequest(self, requestName):
|
|
135
|
+
|
|
136
|
+
if requestName not in self.wqResultsByRequest:
|
|
137
|
+
return None
|
|
138
|
+
# this will include all the possible sites on the requests
|
|
139
|
+
# TODO: when different blocks are located in different site it need to handled
|
|
140
|
+
sites = set()
|
|
141
|
+
for ele in self.wqResultsByRequest[requestName]['Elements']:
|
|
142
|
+
sites = sites | set(possibleSites(ele))
|
|
143
|
+
return sites
|
|
144
|
+
|
|
145
|
+
def getWQElementResultsByRequest(self, requestName = None):
|
|
146
|
+
if requestName:
|
|
147
|
+
return self.wqResultsByRequest.get(requestName, None)
|
|
148
|
+
else:
|
|
149
|
+
return self.wqResultsByRequest
|
|
150
|
+
|
|
151
|
+
def printSummary(self, request, detail=False):
|
|
152
|
+
|
|
153
|
+
wqResult = self.getWQElementResultsByRequest(request)
|
|
154
|
+
|
|
155
|
+
if wqResult is None:
|
|
156
|
+
print("No WQ element exist for the status given")
|
|
157
|
+
return
|
|
158
|
+
print("### summary for %s ###" % request )
|
|
159
|
+
print(" Priority: %s, available elements: %s " % (wqResult["Priority"], len(wqResult['Elements'])))
|
|
160
|
+
|
|
161
|
+
sites = self.getPossibleSitesByRequest(request)
|
|
162
|
+
print(" Possible sites to run: %s" % list(sites))
|
|
163
|
+
|
|
164
|
+
higher = self.elementsWithHigherPriorityInSameSites(request)
|
|
165
|
+
total = 0
|
|
166
|
+
totalJobs = 0
|
|
167
|
+
for request in higher:
|
|
168
|
+
wqResult = higher[request]
|
|
169
|
+
availableEle = wqResult.availableItems()
|
|
170
|
+
if not availableEle:
|
|
171
|
+
continue
|
|
172
|
+
total += len(availableEle)
|
|
173
|
+
wqAvailResult = WorkQueueElementResult(Elements=availableEle)
|
|
174
|
+
totalJobs += wqAvailResult['Jobs']
|
|
175
|
+
maxJobEle = wqAvailResult.getMaxJobElement()
|
|
176
|
+
minJobEle = wqAvailResult.getMinJobElement()
|
|
177
|
+
if detail:
|
|
178
|
+
print(" Higher priority elements by request:")
|
|
179
|
+
print("""%s: Priority: %s, available elements: %s, total jobs: %s,
|
|
180
|
+
max jobs: %s (element_id: %s), min jobs: %s (element_id: %s)""" % (
|
|
181
|
+
request, wqAvailResult["Priority"], availableEle, wqAvailResult['Jobs'],
|
|
182
|
+
maxJobEle["Jobs"], maxJobEle.id,
|
|
183
|
+
minJobEle["Jobs"], minJobEle.id))
|
|
184
|
+
print(" Higher priority elements: %s, total available jobs: %s" % (total, totalJobs))
|
|
185
|
+
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
WorkQueue EndPolicyInterface
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from WMCore.WorkQueue.Policy.PolicyInterface import PolicyInterface
|
|
11
|
+
from WMCore.WorkQueue.DataStructs.WorkQueueElementResult import WorkQueueElementResult as WQEResult
|
|
12
|
+
|
|
13
|
+
class EndPolicyInterface(PolicyInterface):
|
|
14
|
+
"""Interface for end policies"""
|
|
15
|
+
def __init__(self, **args):
|
|
16
|
+
PolicyInterface.__init__(self, **args)
|
|
17
|
+
self.results = []
|
|
18
|
+
|
|
19
|
+
def __call__(self, elements, parents):
|
|
20
|
+
"""Apply policy to given elements"""
|
|
21
|
+
for parent in parents:
|
|
22
|
+
elements_for_parent = []
|
|
23
|
+
for element in elements:
|
|
24
|
+
if element['ParentQueueId'] == parent.id:
|
|
25
|
+
elements_for_parent.append(element)
|
|
26
|
+
result = WQEResult(ParentQueueId = parent.id,
|
|
27
|
+
ParentQueueElement = parent,
|
|
28
|
+
Elements = elements_for_parent)
|
|
29
|
+
self.results.append(result)
|
|
30
|
+
|
|
31
|
+
self.applyPolicy() # do plugin logic
|
|
32
|
+
return self.results
|
|
33
|
+
|
|
34
|
+
def applyPolicy(self):
|
|
35
|
+
"""Extend in sub classes for custom behaviour"""
|
|
36
|
+
forceStatus = None
|
|
37
|
+
for result in self.results:
|
|
38
|
+
result['ParentQueueElement'].updateWithResult(result)
|
|
39
|
+
# check for a cancellation request
|
|
40
|
+
if result['ParentQueueElement'].isCancelRequested():
|
|
41
|
+
forceStatus = 'CancelRequested'
|
|
42
|
+
if forceStatus:
|
|
43
|
+
# cancel whole request
|
|
44
|
+
[x.__setitem__('Status', forceStatus) for x in self.results]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
SingleShot EndPolicy
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from WMCore.WorkQueue.Policy.End.EndPolicyInterface import EndPolicyInterface
|
|
12
|
+
|
|
13
|
+
class SingleShot(EndPolicyInterface):
|
|
14
|
+
"""
|
|
15
|
+
o No Retries
|
|
16
|
+
"""
|
|
17
|
+
def __init__(self, **args):
|
|
18
|
+
EndPolicyInterface.__init__(self, **args)
|
|
19
|
+
|
|
20
|
+
def applyPolicy(self):
|
|
21
|
+
"""Apply the given policy"""
|
|
22
|
+
EndPolicyInterface.applyPolicy(self)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
WorkQueue End Policy
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from WMCore.WMFactory import WMFactory
|
|
8
|
+
|
|
9
|
+
endFac = WMFactory(__name__, __name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def endPolicy(elements, parents=None, args=None):
|
|
13
|
+
"""Load an end policy"""
|
|
14
|
+
|
|
15
|
+
# load policy and apply
|
|
16
|
+
if not args:
|
|
17
|
+
args = {}
|
|
18
|
+
if elements:
|
|
19
|
+
policy = elements[0]['EndPolicy']
|
|
20
|
+
elif parents:
|
|
21
|
+
policy = parents[0]['EndPolicy']
|
|
22
|
+
else:
|
|
23
|
+
raise RuntimeError("Can't get policy, no elements or parents")
|
|
24
|
+
name = policy['policyName']
|
|
25
|
+
args = args.get(name, {})
|
|
26
|
+
args.update(policy)
|
|
27
|
+
return endFac.loadObject(name,
|
|
28
|
+
args,
|
|
29
|
+
storeInCache=False)(elements, parents)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
__all__ = []
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
WorkQueue PolicyInterface
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
from builtins import object
|
|
7
|
+
import logging
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PolicyInterface(object):
|
|
14
|
+
"""Interface for policies"""
|
|
15
|
+
def __init__(self, **args):
|
|
16
|
+
self.logger = args.pop('logger') if args.get('logger') else logging.getLogger()
|
|
17
|
+
self.args = deepcopy(args)
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
WorkQueue splitting by block
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import print_function, division
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from math import ceil
|
|
10
|
+
|
|
11
|
+
from WMCore.WorkQueue.Policy.Start.StartPolicyInterface import StartPolicyInterface
|
|
12
|
+
from WMCore.WorkQueue.WorkQueueExceptions import WorkQueueWMSpecError
|
|
13
|
+
from WMCore.WorkQueue.WorkQueueUtils import makeLocationsList
|
|
14
|
+
from WMCore import Lexicon
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Block(StartPolicyInterface):
|
|
18
|
+
"""Split elements into blocks"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, **args):
|
|
21
|
+
StartPolicyInterface.__init__(self, **args)
|
|
22
|
+
self.args.setdefault('SliceType', 'NumberOfFiles')
|
|
23
|
+
self.args.setdefault('SliceSize', 1)
|
|
24
|
+
self.lumiType = "NumberOfLumis"
|
|
25
|
+
|
|
26
|
+
# Initialize a list of sites where the data is
|
|
27
|
+
self.sites = []
|
|
28
|
+
|
|
29
|
+
# Initialize modifiers of the policy
|
|
30
|
+
self.blockBlackListModifier = []
|
|
31
|
+
|
|
32
|
+
def split(self):
|
|
33
|
+
"""Apply policy to spec"""
|
|
34
|
+
dbs = self.dbs()
|
|
35
|
+
for block in self.validBlocks(self.initialTask, dbs):
|
|
36
|
+
# set the parent flag for processing only for clarity on the couch doc
|
|
37
|
+
parentList = {}
|
|
38
|
+
parentFlag = False
|
|
39
|
+
# TODO this is slow process needs to change in DBS3
|
|
40
|
+
if self.initialTask.parentProcessingFlag():
|
|
41
|
+
parentFlag = True
|
|
42
|
+
parentBlocks = dbs.listBlockParents(block["block"])
|
|
43
|
+
for blockName in parentBlocks:
|
|
44
|
+
if self.initialTask.getTrustSitelists().get('trustlists'):
|
|
45
|
+
parentList[blockName] = self.sites
|
|
46
|
+
else:
|
|
47
|
+
blockLocations = self.blockLocationRucioPhedex(blockName)
|
|
48
|
+
parentList[blockName] = self.cric.PNNstoPSNs(blockLocations)
|
|
49
|
+
|
|
50
|
+
# there could be 0 event files in that case we can't estimate the number of jobs created.
|
|
51
|
+
# We set Jobs to 1 for that case.
|
|
52
|
+
# If we need more realistic estimate, we need to dry run the spliting the jobs.
|
|
53
|
+
estimateJobs = max(1, ceil(block[self.args['SliceType']] / self.args['SliceSize']))
|
|
54
|
+
|
|
55
|
+
self.newQueueElement(Inputs={block['block']: self.data.get(block['block'], [])},
|
|
56
|
+
ParentFlag=parentFlag,
|
|
57
|
+
ParentData=parentList,
|
|
58
|
+
NumberOfLumis=int(block[self.lumiType]),
|
|
59
|
+
NumberOfFiles=int(block['NumberOfFiles']),
|
|
60
|
+
NumberOfEvents=int(block['NumberOfEvents']),
|
|
61
|
+
Jobs=estimateJobs,
|
|
62
|
+
OpenForNewData=False,
|
|
63
|
+
NoInputUpdate=self.initialTask.getTrustSitelists().get('trustlists'),
|
|
64
|
+
NoPileupUpdate=self.initialTask.getTrustSitelists().get('trustPUlists')
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def validate(self):
|
|
68
|
+
"""Check args and spec work with block splitting"""
|
|
69
|
+
StartPolicyInterface.validateCommon(self)
|
|
70
|
+
|
|
71
|
+
if not self.initialTask.inputDataset():
|
|
72
|
+
raise WorkQueueWMSpecError(self.wmspec, 'No input dataset')
|
|
73
|
+
|
|
74
|
+
def validBlocks(self, task, dbs):
|
|
75
|
+
"""Return blocks that pass the input data restriction"""
|
|
76
|
+
datasetPath = task.getInputDatasetPath()
|
|
77
|
+
validBlocks = []
|
|
78
|
+
|
|
79
|
+
blockWhiteList = task.inputBlockWhitelist()
|
|
80
|
+
blockBlackList = task.inputBlockBlacklist()
|
|
81
|
+
runWhiteList = task.inputRunWhitelist()
|
|
82
|
+
runBlackList = task.inputRunBlacklist()
|
|
83
|
+
if task.getLumiMask(): # if we have a lumi mask get only the relevant blocks
|
|
84
|
+
maskedBlocks = self.getMaskedBlocks(task, dbs, datasetPath)
|
|
85
|
+
if task.getTrustSitelists().get('trustlists'):
|
|
86
|
+
siteWhitelist = task.siteWhitelist()
|
|
87
|
+
siteBlacklist = task.siteBlacklist()
|
|
88
|
+
self.sites = makeLocationsList(siteWhitelist, siteBlacklist)
|
|
89
|
+
|
|
90
|
+
blocks = []
|
|
91
|
+
# Take data inputs or from spec
|
|
92
|
+
if not self.data:
|
|
93
|
+
if blockWhiteList:
|
|
94
|
+
self.data = dict((block, []) for block in blockWhiteList)
|
|
95
|
+
else:
|
|
96
|
+
self.data = {datasetPath: []} # same structure as in WorkQueueElement
|
|
97
|
+
|
|
98
|
+
for data in self.data:
|
|
99
|
+
if data.find('#') > -1:
|
|
100
|
+
Lexicon.block(data) # check block name
|
|
101
|
+
datasetPath = str(data.split('#')[0])
|
|
102
|
+
blocks.append(str(data))
|
|
103
|
+
else:
|
|
104
|
+
Lexicon.dataset(data) # check dataset name
|
|
105
|
+
for block in dbs.listFileBlocks(data):
|
|
106
|
+
blocks.append(str(block))
|
|
107
|
+
|
|
108
|
+
for blockName in blocks:
|
|
109
|
+
# check block restrictions
|
|
110
|
+
if blockWhiteList and blockName not in blockWhiteList:
|
|
111
|
+
continue
|
|
112
|
+
if blockName in blockBlackList:
|
|
113
|
+
continue
|
|
114
|
+
if blockName in self.blockBlackListModifier:
|
|
115
|
+
# Don't duplicate blocks rejected before or blocks that were included and therefore are now in the blacklist
|
|
116
|
+
continue
|
|
117
|
+
if task.getLumiMask() and blockName not in maskedBlocks:
|
|
118
|
+
logging.warning("Block %s doesn't pass the lumi mask constraints", blockName)
|
|
119
|
+
self.rejectedWork.append(blockName)
|
|
120
|
+
continue
|
|
121
|
+
|
|
122
|
+
block = self._getBlockSummary(dbs, datasetPath, blockName)
|
|
123
|
+
if not block:
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
# check lumi restrictions
|
|
127
|
+
if task.getLumiMask():
|
|
128
|
+
accepted_lumis = sum([len(maskedBlocks[blockName][lfn].getLumis()) for lfn in maskedBlocks[blockName]])
|
|
129
|
+
# use the information given from getMaskedBlocks to compute che size of the block
|
|
130
|
+
block['NumberOfFiles'] = len(maskedBlocks[blockName])
|
|
131
|
+
# ratio = lumis which are ok in the block / total num lumis
|
|
132
|
+
ratioAccepted = accepted_lumis / block['NumberOfLumis']
|
|
133
|
+
block['NumberOfEvents'] = block['NumberOfEvents'] * ratioAccepted
|
|
134
|
+
block[self.lumiType] = accepted_lumis
|
|
135
|
+
# check run restrictions
|
|
136
|
+
elif runWhiteList or runBlackList:
|
|
137
|
+
# listRunLumis returns a dictionary with the lumi sections per run
|
|
138
|
+
runLumis = dbs.listRunLumis(block=block['block'])
|
|
139
|
+
runs = set(runLumis.keys())
|
|
140
|
+
recalculateLumiCounts = False
|
|
141
|
+
if len(runs) > 1:
|
|
142
|
+
# If more than one run in the block
|
|
143
|
+
# Then we must calculate the lumi counts after filtering the run list
|
|
144
|
+
# This has to be done rarely and requires calling DBS file information
|
|
145
|
+
recalculateLumiCounts = True
|
|
146
|
+
|
|
147
|
+
# apply blacklist
|
|
148
|
+
runs = runs.difference(runBlackList)
|
|
149
|
+
# if whitelist only accept listed runs
|
|
150
|
+
if runWhiteList:
|
|
151
|
+
runs = runs.intersection(runWhiteList)
|
|
152
|
+
# any runs left are ones we will run on, if none ignore block
|
|
153
|
+
if not runs:
|
|
154
|
+
logging.warning("Block %s doesn't pass the runs constraints", blockName)
|
|
155
|
+
self.rejectedWork.append(blockName)
|
|
156
|
+
continue
|
|
157
|
+
|
|
158
|
+
if len(runs) == len(runLumis):
|
|
159
|
+
# If there is no change in the runs, then we can skip recalculating lumi counts
|
|
160
|
+
recalculateLumiCounts = False
|
|
161
|
+
|
|
162
|
+
if recalculateLumiCounts:
|
|
163
|
+
# Recalculate effective size of block
|
|
164
|
+
# We pull out file info, since we don't do this often
|
|
165
|
+
acceptedLumiCount = 0
|
|
166
|
+
acceptedEventCount = 0
|
|
167
|
+
acceptedFileCount = 0
|
|
168
|
+
fileInfo = dbs.listFilesInBlock(fileBlockName=block['block'])
|
|
169
|
+
for fileEntry in fileInfo:
|
|
170
|
+
acceptedFile = False
|
|
171
|
+
acceptedFileLumiCount = 0
|
|
172
|
+
for lumiInfo in fileEntry['LumiList']:
|
|
173
|
+
runNumber = lumiInfo['RunNumber']
|
|
174
|
+
if runNumber in runs:
|
|
175
|
+
acceptedFile = True
|
|
176
|
+
acceptedFileLumiCount += 1
|
|
177
|
+
acceptedLumiCount += len(lumiInfo['LumiSectionNumber'])
|
|
178
|
+
if acceptedFile:
|
|
179
|
+
acceptedFileCount += 1
|
|
180
|
+
if len(fileEntry['LumiList']) != acceptedFileLumiCount:
|
|
181
|
+
acceptedEventCount += acceptedFileLumiCount * fileEntry['NumberOfEvents'] / len(fileEntry['LumiList'])
|
|
182
|
+
else:
|
|
183
|
+
acceptedEventCount += fileEntry['NumberOfEvents']
|
|
184
|
+
block[self.lumiType] = acceptedLumiCount
|
|
185
|
+
block['NumberOfFiles'] = acceptedFileCount
|
|
186
|
+
block['NumberOfEvents'] = acceptedEventCount
|
|
187
|
+
# save locations
|
|
188
|
+
if task.getTrustSitelists().get('trustlists'):
|
|
189
|
+
self.data[block['block']] = self.sites
|
|
190
|
+
else:
|
|
191
|
+
blockLocations = self.blockLocationRucioPhedex(block['block'])
|
|
192
|
+
self.data[block['block']] = self.cric.PNNstoPSNs(blockLocations)
|
|
193
|
+
|
|
194
|
+
# TODO: need to decide what to do when location is no find.
|
|
195
|
+
# There could be case for network problem (no connection to dbs, phedex)
|
|
196
|
+
# or DBS se is not recorded (This will be retried anyway by location mapper)
|
|
197
|
+
if not self.data[block['block']]:
|
|
198
|
+
self.data[block['block']] = ["NoInitialSite"]
|
|
199
|
+
# # No sites for this block, move it to rejected
|
|
200
|
+
# self.rejectedWork.append(blockName)
|
|
201
|
+
# continue
|
|
202
|
+
|
|
203
|
+
validBlocks.append(block)
|
|
204
|
+
return validBlocks
|
|
205
|
+
|
|
206
|
+
def _getBlockSummary(self, dbsObj, datasetPath, blockName):
|
|
207
|
+
"""
|
|
208
|
+
Retrieve a summary for this block from both DBS and Rucio. If the block
|
|
209
|
+
has 0 valid files in DBS, or 0 files in Rucio, it is then marked as
|
|
210
|
+
rejected and skipped from the work creation. Otherwise, the DBS summary
|
|
211
|
+
is returned.
|
|
212
|
+
:param dbsObj: instance to the DBS3Reader object
|
|
213
|
+
:param datasetPath: string with the input dataset name
|
|
214
|
+
:param blockName: string with the block name
|
|
215
|
+
:return: either an empty dictionary, or the DBS summary dictionary
|
|
216
|
+
"""
|
|
217
|
+
# blocks with 0 valid files should be ignored
|
|
218
|
+
# - ideally they would be deleted but dbs can't delete blocks
|
|
219
|
+
block = dbsObj.getDBSSummaryInfo(dataset=datasetPath, block=blockName)
|
|
220
|
+
if int(block.get('NumberOfFiles', 0)) == 0:
|
|
221
|
+
logging.warning("Block %s being rejected for lack of valid files in DBS to process", blockName)
|
|
222
|
+
self.badWork.append(blockName)
|
|
223
|
+
return dict()
|
|
224
|
+
# blocks with 0 files in Rucio should be ignored as well
|
|
225
|
+
blockRucio = self.rucio.getDID(didName=blockName, dynamic=False)
|
|
226
|
+
if not blockRucio.get('length'):
|
|
227
|
+
logging.warning("Block %s being rejected for lack of files in Rucio to process", blockName)
|
|
228
|
+
self.badWork.append(blockName)
|
|
229
|
+
return dict()
|
|
230
|
+
return block
|
|
231
|
+
|
|
232
|
+
def modifyPolicyForWorkAddition(self, inboxElement):
|
|
233
|
+
"""
|
|
234
|
+
A block blacklist modifier will be created,
|
|
235
|
+
this policy object will split excluding the blocks in both the spec
|
|
236
|
+
blacklist and the blacklist modified
|
|
237
|
+
"""
|
|
238
|
+
# Get the already processed input blocks from the inbox element
|
|
239
|
+
self.blockBlackListModifier = inboxElement.get('ProcessedInputs', [])
|
|
240
|
+
self.blockBlackListModifier.extend(inboxElement.get('RejectedInputs', []))
|
|
241
|
+
|
|
242
|
+
def newDataAvailable(self, task, inbound):
|
|
243
|
+
"""
|
|
244
|
+
In the case of the block policy, the new data available
|
|
245
|
+
returns True if it finds at least one open block.
|
|
246
|
+
"""
|
|
247
|
+
self.initialTask = task
|
|
248
|
+
dbs = self.dbs()
|
|
249
|
+
allBlocks = dbs.listFileBlocks(task.getInputDatasetPath())
|
|
250
|
+
newBlocks = set(allBlocks) - set(self.rejectedWork) - set(self.badWork)
|
|
251
|
+
return bool(newBlocks)
|
|
252
|
+
|
|
253
|
+
@staticmethod
|
|
254
|
+
def supportsWorkAddition():
|
|
255
|
+
"""
|
|
256
|
+
Block start policy supports continuous addition of work
|
|
257
|
+
"""
|
|
258
|
+
return True
|