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,492 @@
|
|
|
1
|
+
from builtins import str, bytes, object
|
|
2
|
+
from future.utils import viewitems
|
|
3
|
+
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
from WMCore.Database.CMSCouch import CouchServer, CouchConflictError
|
|
6
|
+
from WMCore.Lexicon import splitCouchServiceURL
|
|
7
|
+
from WMCore.WMSpec.WMWorkload import WMWorkloadHelper
|
|
8
|
+
from WMCore.WorkQueue.DataStructs.WorkQueueElement import STATES
|
|
9
|
+
from WMCore.WorkQueue.DataStructs.CouchWorkQueueElement import CouchWorkQueueElement
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def convertWQElementsStatusToWFStatus(elementsStatusSet):
|
|
13
|
+
"""
|
|
14
|
+
Defined Workflow status from its WorkQeuueElement status.
|
|
15
|
+
:param: elementsStatusSet - dictionary of {request_name: set of all WQE status of this request, ...}
|
|
16
|
+
:returns: request status
|
|
17
|
+
|
|
18
|
+
Here is the mapping between request status and the GQE status
|
|
19
|
+
1. acquired: all the GQEs are either Available or Negotiating.
|
|
20
|
+
Work is still in GQ, but not LQ.
|
|
21
|
+
2. running-open: at least one of the GQEs are in Acquired status.
|
|
22
|
+
3. running-closed: all the GQEs are in Running or beyond status.
|
|
23
|
+
No Available/Negotiating/Acquired status, all the work is in WMBS db (in agents)
|
|
24
|
+
4. completed: all the GQEs are in a final status, like Done/Canceled/Failed.
|
|
25
|
+
All work is finished in WMBS (excluding cleanup and logcollect)
|
|
26
|
+
5. failed: all the GQEs are in Failed status. If the workflow has multiple GQEs
|
|
27
|
+
and only a few are in Failed status, then just follow the usual request status.
|
|
28
|
+
6. canceled: used to distinguish requests that have been correctly canceled,
|
|
29
|
+
coming from workflows either aborted or force-complete. This state does not
|
|
30
|
+
trigger a workflow status transition.
|
|
31
|
+
"""
|
|
32
|
+
if not elementsStatusSet:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
forceCompleted = set(["CancelRequested"])
|
|
36
|
+
available = set(["Available", "Negotiating", "Failed"])
|
|
37
|
+
acquired = set(["Acquired"])
|
|
38
|
+
running = set(["Running"])
|
|
39
|
+
runningOpen = set(["Available", "Negotiating", "Acquired"])
|
|
40
|
+
runningClosed = set(["Running", "Done", "Canceled"])
|
|
41
|
+
canceled = set(["CancelRequested", "Done", "Canceled", "Failed"])
|
|
42
|
+
completed = set(["Done", "Canceled", "Failed"])
|
|
43
|
+
failed = set(["Failed"])
|
|
44
|
+
|
|
45
|
+
# Just a reminder:
|
|
46
|
+
# <= every element in the left set is also in the right set
|
|
47
|
+
# & return elements common between the left and right set
|
|
48
|
+
if elementsStatusSet == forceCompleted: # all WQEs in CancelRequested
|
|
49
|
+
return "canceled"
|
|
50
|
+
elif elementsStatusSet == acquired: # all WQEs in Acquired
|
|
51
|
+
return "running-open"
|
|
52
|
+
elif elementsStatusSet == running: # all WQEs in Running
|
|
53
|
+
return "running-closed"
|
|
54
|
+
elif elementsStatusSet == failed: # all WQEs in Failed
|
|
55
|
+
return "failed"
|
|
56
|
+
elif elementsStatusSet <= available: # all WQEs still in GQ
|
|
57
|
+
return "acquired"
|
|
58
|
+
elif elementsStatusSet <= completed: # all WQEs in a final state
|
|
59
|
+
return "completed"
|
|
60
|
+
elif elementsStatusSet <= canceled: # some WQEs still waiting to be cancelled
|
|
61
|
+
return "canceled"
|
|
62
|
+
elif elementsStatusSet & runningOpen: # at least 1 WQE still in GQ
|
|
63
|
+
return "running-open"
|
|
64
|
+
elif elementsStatusSet & runningClosed: # all WQEs already in LQ and WMBS
|
|
65
|
+
return "running-closed"
|
|
66
|
+
else:
|
|
67
|
+
# transitional status. Negotiating status won't be changed.
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# TODO: this could be derived from the Service class to use client side caching
|
|
72
|
+
class WorkQueue(object):
|
|
73
|
+
"""
|
|
74
|
+
API for dealing with retrieving information from WorkQueue DataService
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def __init__(self, couchURL, dbName=None, inboxDBName=None):
|
|
78
|
+
# if dbName not given assume we have to split
|
|
79
|
+
if not dbName:
|
|
80
|
+
couchURL, dbName = splitCouchServiceURL(couchURL)
|
|
81
|
+
self.hostWithAuth = couchURL
|
|
82
|
+
self.server = CouchServer(couchURL)
|
|
83
|
+
self.db = self.server.connectDatabase(dbName, create=False)
|
|
84
|
+
if not inboxDBName:
|
|
85
|
+
inboxDBName = "%s_inbox" % dbName
|
|
86
|
+
self.inboxDB = self.server.connectDatabase(inboxDBName, create=False)
|
|
87
|
+
self.defaultOptions = {'stale': "update_after", 'reduce': True, 'group': True}
|
|
88
|
+
self.eleKey = 'WMCore.WorkQueue.DataStructs.WorkQueueElement.WorkQueueElement'
|
|
89
|
+
self.states = STATES
|
|
90
|
+
|
|
91
|
+
def getTopLevelJobsByRequest(self):
|
|
92
|
+
"""Get data items we have work in the queue for"""
|
|
93
|
+
|
|
94
|
+
data = self.db.loadView('WorkQueue', 'jobsByRequest', self.defaultOptions)
|
|
95
|
+
return [{'request_name': x['key'],
|
|
96
|
+
'total_jobs': x['value']} for x in data.get('rows', [])]
|
|
97
|
+
|
|
98
|
+
def getChildQueuesAndStatus(self, stale=True):
|
|
99
|
+
"""
|
|
100
|
+
Returns some stats for the workqueue elements in each ChildQueue and their status.
|
|
101
|
+
1. total number of expected Jobs (sum)
|
|
102
|
+
2. count of elements (count)
|
|
103
|
+
3. minimum number of expected Jobs in an element
|
|
104
|
+
4. maximum number of expected Jobs in an element
|
|
105
|
+
5. sum of the squares of the expected Job in each element
|
|
106
|
+
|
|
107
|
+
Also reformat the output such that it's MONIT IT friendly and easier to aggregate.
|
|
108
|
+
"""
|
|
109
|
+
options = {'reduce': True, 'group_level': 2}
|
|
110
|
+
if stale:
|
|
111
|
+
options['stale'] = 'update_after'
|
|
112
|
+
|
|
113
|
+
data = self.db.loadView('WorkQueue', 'jobsByChildQueueAndStatus', options)
|
|
114
|
+
result = []
|
|
115
|
+
for x in data.get('rows', []):
|
|
116
|
+
item = {'agent_name': self._getShortName(x['key'][0]),
|
|
117
|
+
'status': x['key'][1]}
|
|
118
|
+
item.update(dict(sum_jobs=x['value']['sum'],
|
|
119
|
+
num_elem=x['value']['count'],
|
|
120
|
+
max_jobs_elem=x['value']['max']))
|
|
121
|
+
result.append(item)
|
|
122
|
+
|
|
123
|
+
return result
|
|
124
|
+
|
|
125
|
+
def getChildQueuesAndPriority(self, stale=True):
|
|
126
|
+
"""
|
|
127
|
+
Returns some stats for the workqueue elements in each ChildQueue and their priority.
|
|
128
|
+
"""
|
|
129
|
+
options = {'reduce': True, 'group_level': 2}
|
|
130
|
+
if stale:
|
|
131
|
+
options['stale'] = 'update_after'
|
|
132
|
+
|
|
133
|
+
data = self.db.loadView('WorkQueue', 'jobsByChildQueueAndPriority', options)
|
|
134
|
+
result = []
|
|
135
|
+
for x in data.get('rows', []):
|
|
136
|
+
item = {'agent_name': self._getShortName(x['key'][0]),
|
|
137
|
+
'priority': int(x['key'][1])}
|
|
138
|
+
item.update(dict(sum_jobs=x['value']['sum'],
|
|
139
|
+
num_elem=x['value']['count'],
|
|
140
|
+
max_jobs_elem=x['value']['max']))
|
|
141
|
+
result.append(item)
|
|
142
|
+
|
|
143
|
+
return result
|
|
144
|
+
|
|
145
|
+
def _getShortName(self, longQueueName):
|
|
146
|
+
"""
|
|
147
|
+
Get a full workqueue queue name (full hostname + port) and return its short name,
|
|
148
|
+
otherwise it fails to get injected into elastic search. E.g.:
|
|
149
|
+
from "http://cmssrv217.fnal.gov:5984" to "cmssrv217"
|
|
150
|
+
"""
|
|
151
|
+
if longQueueName is None:
|
|
152
|
+
return "AgentNotDefined"
|
|
153
|
+
shortName = longQueueName.split('//')[-1]
|
|
154
|
+
shortName = shortName.split('.')[0]
|
|
155
|
+
return shortName
|
|
156
|
+
|
|
157
|
+
def getWMBSUrl(self):
|
|
158
|
+
"""Get data items we have work in the queue for"""
|
|
159
|
+
data = self.db.loadView('WorkQueue', 'wmbsUrl', self.defaultOptions)
|
|
160
|
+
return [x['key'] for x in data.get('rows', [])]
|
|
161
|
+
|
|
162
|
+
def getWMBSUrlByRequest(self):
|
|
163
|
+
"""Get data items we have work in the queue for"""
|
|
164
|
+
data = self.db.loadView('WorkQueue', 'wmbsUrlByRequest', self.defaultOptions)
|
|
165
|
+
return [{'request_name': x['key'][0],
|
|
166
|
+
'wmbs_url': x['key'][1]} for x in data.get('rows', [])]
|
|
167
|
+
|
|
168
|
+
def getJobInjectStatusByRequest(self):
|
|
169
|
+
"""
|
|
170
|
+
This service only provided by global queue
|
|
171
|
+
"""
|
|
172
|
+
data = self.db.loadView('WorkQueue', 'jobInjectStatusByRequest',
|
|
173
|
+
self.defaultOptions)
|
|
174
|
+
return [{'request_name': x['key'][0], x['key'][1]: x['value']}
|
|
175
|
+
for x in data.get('rows', [])]
|
|
176
|
+
|
|
177
|
+
def getAnalyticsData(self):
|
|
178
|
+
"""
|
|
179
|
+
This getInject status and input dataset from workqueue
|
|
180
|
+
"""
|
|
181
|
+
results = self.db.loadView('WorkQueue', 'jobInjectStatusByRequest',
|
|
182
|
+
self.defaultOptions)
|
|
183
|
+
statusByRequest = {}
|
|
184
|
+
for x in results.get('rows', []):
|
|
185
|
+
statusByRequest.setdefault(x['key'][0], {})
|
|
186
|
+
statusByRequest[x['key'][0]][x['key'][1]] = x['value']
|
|
187
|
+
|
|
188
|
+
return statusByRequest
|
|
189
|
+
|
|
190
|
+
def getSiteWhitelistByRequest(self):
|
|
191
|
+
"""
|
|
192
|
+
This service only provided by global queue
|
|
193
|
+
"""
|
|
194
|
+
data = self.db.loadView('WorkQueue', 'siteWhitelistByRequest',
|
|
195
|
+
self.defaultOptions)
|
|
196
|
+
return [{'request_name': x['key'][0], 'site_whitelist': x['key'][1]}
|
|
197
|
+
for x in data.get('rows', [])]
|
|
198
|
+
|
|
199
|
+
def updateElements(self, *elementIds, **updatedParams):
|
|
200
|
+
"""Update given element's (identified by id) with new parameters"""
|
|
201
|
+
if not elementIds:
|
|
202
|
+
return
|
|
203
|
+
eleParams = {}
|
|
204
|
+
if 'RequestPriority' in updatedParams:
|
|
205
|
+
updatedParams['Priority'] = updatedParams.pop('RequestPriority')
|
|
206
|
+
eleParams[self.eleKey] = updatedParams
|
|
207
|
+
conflictIDs = self.db.updateBulkDocumentsWithConflictHandle(elementIds, eleParams, maxConflictLimit=20)
|
|
208
|
+
if conflictIDs:
|
|
209
|
+
raise CouchConflictError("WQ update failed with conflict", data=updatedParams, result=conflictIDs, status=409)
|
|
210
|
+
return
|
|
211
|
+
|
|
212
|
+
def getAvailableWorkflows(self):
|
|
213
|
+
"""Get the workflows that have all their elements
|
|
214
|
+
available in the workqueue"""
|
|
215
|
+
data = self.db.loadView('WorkQueue', 'elementsDetailByWorkflowAndStatus',
|
|
216
|
+
{'reduce': False, 'stale': 'update_after'})
|
|
217
|
+
availableSet = set((x['value']['RequestName'], x['value']['Priority']) for x in data.get('rows', []) if
|
|
218
|
+
x['key'][1] == 'Available')
|
|
219
|
+
notAvailableSet = set((x['value']['RequestName'], x['value']['Priority']) for x in data.get('rows', []) if
|
|
220
|
+
x['key'][1] != 'Available')
|
|
221
|
+
return availableSet - notAvailableSet
|
|
222
|
+
|
|
223
|
+
def cancelWorkflow(self, wf):
|
|
224
|
+
"""
|
|
225
|
+
Cancel a workflow in both workqueue and workqueue_inbox database.
|
|
226
|
+
:param wf: string with the workflow name
|
|
227
|
+
:return: the status code for the couchdb update call
|
|
228
|
+
"""
|
|
229
|
+
# first, update the single workflow workqueue_inbox element, if needed
|
|
230
|
+
inboxData = self.getOpenRequests(inboxFlag=True, options={"key": wf})
|
|
231
|
+
if inboxData:
|
|
232
|
+
updateParams = {self.eleKey: {"OpenForNewData": False}}
|
|
233
|
+
self.inboxDB.updateBulkDocuments(inboxData, updateParams)
|
|
234
|
+
|
|
235
|
+
# now update all of the workqueue elements
|
|
236
|
+
nonCancelableElements = ['Done', 'CancelRequested', 'Canceled', 'Failed']
|
|
237
|
+
data = self.db.loadView('WorkQueue', 'elementsDetailByWorkflowAndStatus',
|
|
238
|
+
{'startkey': [wf], 'endkey': [wf, {}],
|
|
239
|
+
'reduce': False})
|
|
240
|
+
elements = [x['id'] for x in data.get('rows', []) if x['key'][1] not in nonCancelableElements]
|
|
241
|
+
return self.updateElements(*elements, Status='CancelRequested')
|
|
242
|
+
|
|
243
|
+
def updatePriority(self, wf, priority):
|
|
244
|
+
"""Update priority of a workflow, this implies
|
|
245
|
+
updating the spec and the priority of the Available elements"""
|
|
246
|
+
# Update elements in Available status
|
|
247
|
+
data = self.db.loadView('WorkQueue', 'elementsDetailByWorkflowAndStatus',
|
|
248
|
+
{'startkey': [wf], 'endkey': [wf, {}],
|
|
249
|
+
'reduce': False})
|
|
250
|
+
elementsToUpdate = [x['id'] for x in data.get('rows', [])]
|
|
251
|
+
if elementsToUpdate:
|
|
252
|
+
self.updateElements(*elementsToUpdate, Priority=priority)
|
|
253
|
+
# Update the spec, if it exists
|
|
254
|
+
if self.db.documentExists(wf):
|
|
255
|
+
wmspec = WMWorkloadHelper()
|
|
256
|
+
wmspec.load(self.hostWithAuth + "/%s/%s/spec" % (self.db.name, wf))
|
|
257
|
+
wmspec.setPriority(priority)
|
|
258
|
+
dummy_values = {'name': wmspec.name()}
|
|
259
|
+
wmspec.saveCouch(self.hostWithAuth, self.db.name, dummy_values)
|
|
260
|
+
return
|
|
261
|
+
|
|
262
|
+
def updateElementsByWorkflow(self, workload, updateParams, status=None):
|
|
263
|
+
"""
|
|
264
|
+
Update all available WorkQueue elements of a given workflow with a set
|
|
265
|
+
of arguments provided through the `updateParams` dictionary
|
|
266
|
+
:param workload: A workflow spec
|
|
267
|
+
:param updateParams: A dictionary with parameters to be updated
|
|
268
|
+
:param status: A list of allowed WorkQueue elements statuses to be considered for updating
|
|
269
|
+
Default: None - do not filter by status
|
|
270
|
+
:return: No value, raises exceptions from internal methods in case of errors.
|
|
271
|
+
"""
|
|
272
|
+
# Fetch the whole view with Workqueue elements per given workflow
|
|
273
|
+
wfName = workload.name()
|
|
274
|
+
data = self.db.loadView('WorkQueue', 'elementsDetailByWorkflowAndStatus',
|
|
275
|
+
{'startkey': [wfName], 'endkey': [wfName, {}],
|
|
276
|
+
'reduce': False})
|
|
277
|
+
|
|
278
|
+
# Fetch only a list of WorkQueue element Ids && Filter them by allowed status
|
|
279
|
+
if status:
|
|
280
|
+
elementsToUpdate = [x['id'] for x in data.get('rows', []) if x['value']['Status'] in status]
|
|
281
|
+
else:
|
|
282
|
+
elementsToUpdate = [x['id'] for x in data.get('rows', [])]
|
|
283
|
+
|
|
284
|
+
# Update all WorkQueue elements with the parameters provided in a single push
|
|
285
|
+
if elementsToUpdate:
|
|
286
|
+
self.updateElements(*elementsToUpdate, **updateParams)
|
|
287
|
+
|
|
288
|
+
# Update the spec, if it exists
|
|
289
|
+
if self.db.documentExists(wfName):
|
|
290
|
+
# Update all workload parameters based on the full reqArgs dictionary
|
|
291
|
+
workload.updateWorkloadArgs(updateParams)
|
|
292
|
+
# Commit the changes of the current workload object to the database:
|
|
293
|
+
metadata = {'name': wfName}
|
|
294
|
+
workload.saveCouch(self.hostWithAuth, self.db.name, metadata=metadata)
|
|
295
|
+
return
|
|
296
|
+
|
|
297
|
+
def getWorkflowNames(self, inboxFlag=False):
|
|
298
|
+
"""Get workflow names from workqueue db"""
|
|
299
|
+
if inboxFlag:
|
|
300
|
+
db = self.inboxDB
|
|
301
|
+
else:
|
|
302
|
+
db = self.db
|
|
303
|
+
data = db.loadView('WorkQueue', 'elementsByWorkflow', self.defaultOptions)
|
|
304
|
+
return [x['key'] for x in data.get('rows', [])]
|
|
305
|
+
|
|
306
|
+
def deleteWQElementsByWorkflow(self, workflowNames):
|
|
307
|
+
"""
|
|
308
|
+
delete workqueue elements belongs to given workflow names
|
|
309
|
+
"""
|
|
310
|
+
deleted = 0
|
|
311
|
+
dbs = [self.db, self.inboxDB]
|
|
312
|
+
if not isinstance(workflowNames, list):
|
|
313
|
+
workflowNames = [workflowNames]
|
|
314
|
+
|
|
315
|
+
if len(workflowNames) == 0:
|
|
316
|
+
return deleted
|
|
317
|
+
|
|
318
|
+
options = {}
|
|
319
|
+
options["stale"] = "ok"
|
|
320
|
+
options["reduce"] = False
|
|
321
|
+
|
|
322
|
+
for couchdb in dbs:
|
|
323
|
+
result = couchdb.loadView("WorkQueue", "elementsByWorkflow", options, workflowNames)
|
|
324
|
+
ids = []
|
|
325
|
+
for entry in result["rows"]:
|
|
326
|
+
ids.append(entry["id"])
|
|
327
|
+
if ids:
|
|
328
|
+
couchdb.bulkDeleteByIDs(ids)
|
|
329
|
+
deleted += len(ids)
|
|
330
|
+
return deleted
|
|
331
|
+
|
|
332
|
+
def getWQElementsByWorkflow(self, workflowNames, inboxFlag=False):
|
|
333
|
+
"""
|
|
334
|
+
Get workqueue elements which belongs to a given workflow name(s)
|
|
335
|
+
:param workflowNames: The workflow name for which we try to fetch the WQE elemtns for (could be a list of names as well)
|
|
336
|
+
:param inboxFlag: A flag to switch quering the inboxDB as well (default: False)
|
|
337
|
+
:return: A list of WQEs
|
|
338
|
+
"""
|
|
339
|
+
if inboxFlag:
|
|
340
|
+
couchdb = self.inboxDB
|
|
341
|
+
else:
|
|
342
|
+
couchdb = self.db
|
|
343
|
+
|
|
344
|
+
if not isinstance(workflowNames, list):
|
|
345
|
+
workflowNames = [workflowNames]
|
|
346
|
+
|
|
347
|
+
options = {}
|
|
348
|
+
options["stale"] = "ok"
|
|
349
|
+
options["reduce"] = False
|
|
350
|
+
options['include_docs'] = True
|
|
351
|
+
|
|
352
|
+
data = couchdb.loadView("WorkQueue", "elementsByWorkflow", options, workflowNames)
|
|
353
|
+
wqeList=[]
|
|
354
|
+
for wqe in data['rows']:
|
|
355
|
+
wqeList.append(CouchWorkQueueElement.fromDocument(couchdb, wqe['doc']))
|
|
356
|
+
return wqeList
|
|
357
|
+
|
|
358
|
+
def getElementsCountAndJobsByWorkflow(self, inboxFlag=False, stale=True):
|
|
359
|
+
"""Get the number of elements and jobs by status and workflow"""
|
|
360
|
+
if inboxFlag:
|
|
361
|
+
db = self.inboxDB
|
|
362
|
+
else:
|
|
363
|
+
db = self.db
|
|
364
|
+
options = {'reduce': True, 'group_level': 2}
|
|
365
|
+
if stale:
|
|
366
|
+
options['stale'] = 'update_after'
|
|
367
|
+
data = db.loadView('WorkQueue', 'jobStatusByRequest', options)
|
|
368
|
+
result = defaultdict(dict)
|
|
369
|
+
for x in data.get('rows', []):
|
|
370
|
+
result[x['key'][0]][x['key'][1]] = {'NumOfElements': x['value']['count'],
|
|
371
|
+
'Jobs': x['value']['sum']}
|
|
372
|
+
return result
|
|
373
|
+
|
|
374
|
+
def _retrieveWorkflowStatus(self, data):
|
|
375
|
+
workflowsStatus = {}
|
|
376
|
+
|
|
377
|
+
for workflow in data:
|
|
378
|
+
statusSet = set(data[workflow].keys())
|
|
379
|
+
status = convertWQElementsStatusToWFStatus(statusSet)
|
|
380
|
+
if status:
|
|
381
|
+
workflowsStatus[workflow] = status
|
|
382
|
+
return workflowsStatus
|
|
383
|
+
|
|
384
|
+
def getWorkflowStatusFromWQE(self, stale=True):
|
|
385
|
+
"""
|
|
386
|
+
only checks workqueue db not inbox db.
|
|
387
|
+
returns and list of workflows by request status
|
|
388
|
+
"""
|
|
389
|
+
data = self.getElementsCountAndJobsByWorkflow(stale=stale)
|
|
390
|
+
return self._retrieveWorkflowStatus(data)
|
|
391
|
+
|
|
392
|
+
def getCompletedWorkflow(self, stale=True):
|
|
393
|
+
"""
|
|
394
|
+
only checks workqueue db not inbox db.
|
|
395
|
+
since inbox db will be cleaned up first when workflow is completed
|
|
396
|
+
"""
|
|
397
|
+
workflowStatus = self.getWorkflowStatusFromWQE(stale=stale)
|
|
398
|
+
return [wf for wf, status in viewitems(workflowStatus) if status == "completed"]
|
|
399
|
+
|
|
400
|
+
def getJobsByStatus(self, inboxFlag=False, group=True):
|
|
401
|
+
"""
|
|
402
|
+
For each WorkQueue element status, returns:
|
|
403
|
+
* total number of jobs (sum)
|
|
404
|
+
* number of workqueue elements (count)
|
|
405
|
+
* biggest number of jobs found in all those elements (max)
|
|
406
|
+
|
|
407
|
+
Use group=False in order to get a final summary of all the elements.
|
|
408
|
+
"""
|
|
409
|
+
if inboxFlag:
|
|
410
|
+
db = self.inboxDB
|
|
411
|
+
else:
|
|
412
|
+
db = self.db
|
|
413
|
+
options = {'reduce': True, 'group': group, 'stale': 'update_after'}
|
|
414
|
+
|
|
415
|
+
data = db.loadView('WorkQueue', 'jobsByStatus', options)
|
|
416
|
+
result = {}
|
|
417
|
+
# Add all WorkQueueElement status to the output
|
|
418
|
+
for st in self.states:
|
|
419
|
+
result[st] = {}
|
|
420
|
+
|
|
421
|
+
for x in data.get('rows', []):
|
|
422
|
+
item = dict(sum_jobs=x['value']['sum'],
|
|
423
|
+
num_elem=x['value']['count'],
|
|
424
|
+
max_jobs_elem=x['value']['max'])
|
|
425
|
+
result[x['key']] = item
|
|
426
|
+
|
|
427
|
+
return result
|
|
428
|
+
|
|
429
|
+
def getJobsByStatusAndPriority(self, stale=True):
|
|
430
|
+
"""
|
|
431
|
+
For each WorkQueue element status, returns a list of:
|
|
432
|
+
* workqueue element priority
|
|
433
|
+
* total number of jobs (sum)
|
|
434
|
+
* number of workqueue elements (count)
|
|
435
|
+
* biggest number of jobs found in all those elements (max)
|
|
436
|
+
"""
|
|
437
|
+
options = {'reduce': True, 'group_level': 2}
|
|
438
|
+
if stale:
|
|
439
|
+
options['stale'] = 'update_after'
|
|
440
|
+
|
|
441
|
+
data = self.db.loadView('WorkQueue', 'jobsByStatusAndPriority', options)
|
|
442
|
+
result = {}
|
|
443
|
+
# Add all WorkQueueElement status to the output
|
|
444
|
+
for st in self.states:
|
|
445
|
+
result[st] = []
|
|
446
|
+
|
|
447
|
+
for x in data.get('rows', []):
|
|
448
|
+
st = x['key'][0]
|
|
449
|
+
prio = x['key'][1]
|
|
450
|
+
item = dict(priority=int(prio), sum_jobs=x['value']['sum'],
|
|
451
|
+
num_elem=x['value']['count'], max_jobs_elem=x['value']['max'])
|
|
452
|
+
result[st].append(item)
|
|
453
|
+
|
|
454
|
+
return result
|
|
455
|
+
|
|
456
|
+
def getElementsByStatus(self, status, inboxFlag=False, stale=True):
|
|
457
|
+
"""
|
|
458
|
+
_getElementsByStatus_
|
|
459
|
+
|
|
460
|
+
Returns the whole elements in workqueue that match the list of status given.
|
|
461
|
+
"""
|
|
462
|
+
if isinstance(status, (str, bytes)):
|
|
463
|
+
status = [status]
|
|
464
|
+
|
|
465
|
+
options = {'stale': 'update_after'} if stale else {}
|
|
466
|
+
options['include_docs'] = True
|
|
467
|
+
|
|
468
|
+
db = self.inboxDB if inboxFlag else self.db
|
|
469
|
+
|
|
470
|
+
data = db.loadView('WorkQueue', 'elementsByStatus', options, status)
|
|
471
|
+
result = {}
|
|
472
|
+
for x in data.get('rows', []):
|
|
473
|
+
# doc may have been deleted already
|
|
474
|
+
if x['doc']:
|
|
475
|
+
result.setdefault(x['key'], [])
|
|
476
|
+
result[x['key']].append(x['doc'])
|
|
477
|
+
|
|
478
|
+
return result
|
|
479
|
+
|
|
480
|
+
def getOpenRequests(self, inboxFlag=False, options=None):
|
|
481
|
+
"""
|
|
482
|
+
Return workflow names that are still opened for new
|
|
483
|
+
data in workqueue
|
|
484
|
+
:param inboxFlag: boolean to select the *_inbox db
|
|
485
|
+
:param options: a dictionary that supports a few view parameters
|
|
486
|
+
:return: a list with unique request names
|
|
487
|
+
"""
|
|
488
|
+
options = options or {}
|
|
489
|
+
options.setdefault("stale", "update_after")
|
|
490
|
+
db = self.inboxDB if inboxFlag else self.db
|
|
491
|
+
data = db.loadView('WorkQueue', 'openRequests', options)
|
|
492
|
+
return [x['key'] for x in data.get('rows', [])]
|
|
File without changes
|