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,419 @@
|
|
|
1
|
+
from __future__ import division, print_function
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from Utils.Utilities import diskUse
|
|
7
|
+
from WMCore.Cache.GenericDataCache import MemoryCacheStruct
|
|
8
|
+
from WMCore.Services.Service import Service
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ReqMgrAux(Service):
|
|
12
|
+
"""
|
|
13
|
+
API for dealing with retrieving information from RequestManager dataservice
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, url, httpDict=None, logger=None):
|
|
18
|
+
"""
|
|
19
|
+
responseType will be either xml or json
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
httpDict = httpDict or {}
|
|
23
|
+
# url is end point
|
|
24
|
+
httpDict['endpoint'] = "%s/data" % url
|
|
25
|
+
httpDict['logger'] = logger if logger else logging.getLogger()
|
|
26
|
+
|
|
27
|
+
# cherrypy converts request.body to params when content type is set
|
|
28
|
+
# application/x-www-form-urlencodeds
|
|
29
|
+
httpDict.setdefault("content_type", 'application/json')
|
|
30
|
+
httpDict.setdefault('cacheduration', 0)
|
|
31
|
+
self.cacheExpire = httpDict['cacheduration']
|
|
32
|
+
httpDict.setdefault("accept_type", "application/json")
|
|
33
|
+
self.encoder = json.dumps
|
|
34
|
+
Service.__init__(self, httpDict)
|
|
35
|
+
# This is only for the unittest: never set it true unless it is unittest
|
|
36
|
+
self._noStale = False
|
|
37
|
+
|
|
38
|
+
def _getResult(self, callname, clearCache=False, args=None, verb="GET",
|
|
39
|
+
encoder=json.loads, decoder=json.loads, contentType=None):
|
|
40
|
+
"""
|
|
41
|
+
_getResult_
|
|
42
|
+
"""
|
|
43
|
+
cfile = callname.replace("/", "_")
|
|
44
|
+
if clearCache:
|
|
45
|
+
self.clearCache(cfile, args, verb)
|
|
46
|
+
|
|
47
|
+
f = self.refreshCache(cfile, callname, args, encoder=encoder,
|
|
48
|
+
verb=verb, contentType=contentType)
|
|
49
|
+
result = f.read()
|
|
50
|
+
f.close()
|
|
51
|
+
|
|
52
|
+
if result and decoder:
|
|
53
|
+
result = decoder(result)
|
|
54
|
+
|
|
55
|
+
return result['result']
|
|
56
|
+
|
|
57
|
+
def _getDataFromMemoryCache(self, callname):
|
|
58
|
+
cache = MemoryCacheStruct(expire=self.cacheExpire, func=self._getResult, initCacheValue={},
|
|
59
|
+
logger=self['logger'], kwargs={'callname': callname, "verb": "GET"})
|
|
60
|
+
return cache.getData()
|
|
61
|
+
|
|
62
|
+
def getCMSSWVersion(self):
|
|
63
|
+
"""
|
|
64
|
+
get dictionary format of architecture and cmssw versions
|
|
65
|
+
i.e.
|
|
66
|
+
{"slc5_amd64_gcc462": [
|
|
67
|
+
"CMSSW_5_3_4_patch1",
|
|
68
|
+
"CMSSW_5_2_9",
|
|
69
|
+
"CMSSW_5_3_4_patch2",
|
|
70
|
+
"CMSSW_5_3_3_cand1_patch1"],
|
|
71
|
+
...
|
|
72
|
+
}
|
|
73
|
+
"""
|
|
74
|
+
return self._getDataFromMemoryCache('cmsswversions')
|
|
75
|
+
|
|
76
|
+
def _updateRecords(self, callName, resource, kwparams):
|
|
77
|
+
"""
|
|
78
|
+
Fetches the original document, locally update it according to
|
|
79
|
+
the key/value pairs provided and update the document.
|
|
80
|
+
:param callName: resource to be requested
|
|
81
|
+
:param resource: name of the resource/document to be updated
|
|
82
|
+
:param kwparams: a dictionary with the content to be updated
|
|
83
|
+
:return: a dictionary with the CouchDB response
|
|
84
|
+
"""
|
|
85
|
+
apiMap = {'wmagentconfig': self.getWMAgentConfig,
|
|
86
|
+
'campaignconfig': self.getCampaignConfig,
|
|
87
|
+
'transferinfo': self.getTransferInfo}
|
|
88
|
+
|
|
89
|
+
thisDoc = apiMap[callName](resource)
|
|
90
|
+
# getWMAgentConfig method returns directly the document, while the others
|
|
91
|
+
# return a list of document(s)
|
|
92
|
+
if isinstance(thisDoc, (list, set)):
|
|
93
|
+
thisDoc = thisDoc[0]
|
|
94
|
+
thisDoc.update(kwparams)
|
|
95
|
+
return self["requests"].put("%s/%s" % (callName, resource), thisDoc)[0]['result']
|
|
96
|
+
|
|
97
|
+
def populateCMSSWVersion(self, tcUrl, **kwargs):
|
|
98
|
+
"""
|
|
99
|
+
Query TagCollector and update the CMSSW versions document in Couch
|
|
100
|
+
:return: a boolean with the result of the operation
|
|
101
|
+
"""
|
|
102
|
+
from WMCore.Services.TagCollector.TagCollector import TagCollector
|
|
103
|
+
cmsswVersions = TagCollector(tcUrl, **kwargs).releases_by_architecture()
|
|
104
|
+
resp = self["requests"].put('cmsswversions', cmsswVersions)[0]['result']
|
|
105
|
+
|
|
106
|
+
if resp and resp[0].get("ok", False):
|
|
107
|
+
self["logger"].info("CMSSW document successfully updated.")
|
|
108
|
+
return True
|
|
109
|
+
|
|
110
|
+
msg = "Failed to update CMSSW document. Response: %s" % resp
|
|
111
|
+
self["logger"].warning(msg)
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
def getWMAgentConfig(self, agentName):
|
|
115
|
+
"""
|
|
116
|
+
retrieve agent configuration reqmgr aux db.
|
|
117
|
+
"""
|
|
118
|
+
agentConfig = self._getDataFromMemoryCache('wmagentconfig/%s' % agentName)
|
|
119
|
+
|
|
120
|
+
if len(agentConfig) != 1:
|
|
121
|
+
# something wrong with database record. returns default value for both case.
|
|
122
|
+
self["logger"].warning("agent config is not correct: %s" % agentConfig)
|
|
123
|
+
return {}
|
|
124
|
+
|
|
125
|
+
return agentConfig[0]
|
|
126
|
+
|
|
127
|
+
def postWMAgentConfig(self, agentName, agentConfig):
|
|
128
|
+
"""
|
|
129
|
+
Create a new WMAgent configuration file in ReqMgrAux.
|
|
130
|
+
If document already exists, nothing happens.
|
|
131
|
+
"""
|
|
132
|
+
return self["requests"].post('wmagentconfig/%s' % agentName, agentConfig)[0]['result']
|
|
133
|
+
|
|
134
|
+
def updateWMAgentConfig(self, agentName, content, inPlace=False):
|
|
135
|
+
"""
|
|
136
|
+
Update the corresponding agent configuration with the content
|
|
137
|
+
provided, replacing the old document.
|
|
138
|
+
If inPlace is set to True, then a modification of the current
|
|
139
|
+
document is performed, according to the key/value pairs provided.
|
|
140
|
+
:param agentName: name of the agent/document in couch
|
|
141
|
+
:param content: a dictionary with the data to be updated
|
|
142
|
+
:param inPlace: a boolean defining whether to perform a replace
|
|
143
|
+
or a update modification
|
|
144
|
+
:return: a boolean with the result of the operation
|
|
145
|
+
"""
|
|
146
|
+
api = 'wmagentconfig'
|
|
147
|
+
if inPlace:
|
|
148
|
+
resp = self._updateRecords(api, agentName, content)
|
|
149
|
+
else:
|
|
150
|
+
resp = self["requests"].put("%s/%s" % (api, agentName), content)[0]['result']
|
|
151
|
+
|
|
152
|
+
if resp and resp[0].get("ok", False):
|
|
153
|
+
self["logger"].info("Update in-place: %s for agent: %s was successful.", inPlace, agentName)
|
|
154
|
+
return True
|
|
155
|
+
|
|
156
|
+
msg = "Failed to update agent: %s in-place: %s. Response: %s" % (agentName, inPlace, resp)
|
|
157
|
+
self["logger"].warning(msg)
|
|
158
|
+
return False
|
|
159
|
+
|
|
160
|
+
def getCampaignConfig(self, campaignName):
|
|
161
|
+
"""
|
|
162
|
+
get campaign config for transferor function in unified ReqMgr2MS.
|
|
163
|
+
"""
|
|
164
|
+
return self._getDataFromMemoryCache('campaignconfig/%s' % campaignName)
|
|
165
|
+
|
|
166
|
+
def postCampaignConfig(self, campaignName, campaignConfig):
|
|
167
|
+
"""
|
|
168
|
+
Create a new campaign configuration document
|
|
169
|
+
|
|
170
|
+
:param campaignName
|
|
171
|
+
:type basestringg
|
|
172
|
+
:param campaignConfig:
|
|
173
|
+
:type dict - only can replace whole campaign no partial parameters
|
|
174
|
+
|
|
175
|
+
campaignName: "HIRun2015":
|
|
176
|
+
campaignConfig: {
|
|
177
|
+
"go": true,
|
|
178
|
+
"labels" : ["02May2016","25Aug2016"],
|
|
179
|
+
"overflow" : {"PRIM" : {}},
|
|
180
|
+
"DDMcopies": {
|
|
181
|
+
"all" : { "N" : 2 }
|
|
182
|
+
},
|
|
183
|
+
"custodial_override" : ["DQMIO"],
|
|
184
|
+
"fractionpass": 1.0,
|
|
185
|
+
"lumisize" : -1,
|
|
186
|
+
"maxcopies" : 1,
|
|
187
|
+
"custodial": "T1_FR_CCIN2P3_MSS",
|
|
188
|
+
"parameters" :{
|
|
189
|
+
"NonCustodialSites" : ["T2_US_Vanderbilt"],
|
|
190
|
+
"SiteBlacklist": [
|
|
191
|
+
"T1_US_FNAL",
|
|
192
|
+
"T2_US_Purdue",
|
|
193
|
+
"T2_US_Caltech",
|
|
194
|
+
"T2_US_Florida",
|
|
195
|
+
"T2_US_Nebraska",
|
|
196
|
+
"T2_US_UCSD",
|
|
197
|
+
"T2_US_Wisconsin"
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
:return: CouchDB response dictionary
|
|
203
|
+
"""
|
|
204
|
+
return self["requests"].post('campaignconfig/%s' % campaignName, campaignConfig)[0]['result']
|
|
205
|
+
|
|
206
|
+
def updateCampaignConfig(self, campaignName, content, inPlace=False):
|
|
207
|
+
"""
|
|
208
|
+
Update the corresponding campaign configuration with the content
|
|
209
|
+
provided, replacing the old document.
|
|
210
|
+
If inPlace is set to True, then a modification of the current
|
|
211
|
+
document is performed, according to the key/value pairs provided.
|
|
212
|
+
:param campaignName: name of the campaign document in couch
|
|
213
|
+
:param content: a dictionary with the data to be updated
|
|
214
|
+
:param inPlace: a boolean defining whether to perform a replace
|
|
215
|
+
or a update modification
|
|
216
|
+
:return: a boolean with the result of the operation
|
|
217
|
+
"""
|
|
218
|
+
api = 'campaignconfig'
|
|
219
|
+
if inPlace:
|
|
220
|
+
resp = self._updateRecords(api, campaignName, content)
|
|
221
|
+
else:
|
|
222
|
+
resp = self["requests"].put("%s/%s" % (api, campaignName), content)[0]['result']
|
|
223
|
+
|
|
224
|
+
if resp and resp[0].get("ok", False):
|
|
225
|
+
self["logger"].info("Update in-place: %s for campaign: %s was successful.", inPlace, campaignName)
|
|
226
|
+
return True
|
|
227
|
+
msg = "Failed to update campaign: %s in-place: %s. Response: %s" % (campaignName, inPlace, resp)
|
|
228
|
+
self["logger"].warning(msg)
|
|
229
|
+
return False
|
|
230
|
+
|
|
231
|
+
def getUnifiedConfig(self, docName=None):
|
|
232
|
+
"""
|
|
233
|
+
Retrieve a Unified document type from the auxiliary db.
|
|
234
|
+
If docName is not provided, then fetch the default UNIFIED_CONFIG doc
|
|
235
|
+
"""
|
|
236
|
+
if docName:
|
|
237
|
+
unifiedConfig = self._getDataFromMemoryCache('unifiedconfig/%s' % docName)
|
|
238
|
+
else:
|
|
239
|
+
unifiedConfig = self._getDataFromMemoryCache('unifiedconfig')
|
|
240
|
+
|
|
241
|
+
if not unifiedConfig:
|
|
242
|
+
self["logger"].warning("Unified configuration document not found. Result: %s", unifiedConfig)
|
|
243
|
+
|
|
244
|
+
return unifiedConfig
|
|
245
|
+
|
|
246
|
+
def postUnifiedConfig(self, unifiedConfig, docName=None):
|
|
247
|
+
"""
|
|
248
|
+
Create a new unified configuration document
|
|
249
|
+
"""
|
|
250
|
+
if docName:
|
|
251
|
+
return self["requests"].post('unifiedconfig/%s' % docName, unifiedConfig)[0]['result']
|
|
252
|
+
return self["requests"].post('unifiedconfig', unifiedConfig)[0]['result']
|
|
253
|
+
|
|
254
|
+
def updateUnifiedConfig(self, content, docName=None):
|
|
255
|
+
"""
|
|
256
|
+
Update the unified configuration with the content provided, replacing
|
|
257
|
+
the old document.
|
|
258
|
+
:param content: a dictionary with the data to be updated
|
|
259
|
+
:return: a boolean with the result of the operation
|
|
260
|
+
"""
|
|
261
|
+
api = 'unifiedconfig'
|
|
262
|
+
if docName:
|
|
263
|
+
resp = self["requests"].put("%s/%s" % (api, docName), content)[0]['result']
|
|
264
|
+
else:
|
|
265
|
+
resp = self["requests"].put("%s" % api, content)[0]['result']
|
|
266
|
+
|
|
267
|
+
if resp and resp[0].get("ok", False):
|
|
268
|
+
self["logger"].info("Unified configuration successfully updated.")
|
|
269
|
+
return True
|
|
270
|
+
|
|
271
|
+
self["logger"].warning("Failed to update the unified configuration. Response: %s", resp)
|
|
272
|
+
return False
|
|
273
|
+
|
|
274
|
+
def getTransferInfo(self, docName):
|
|
275
|
+
"""
|
|
276
|
+
get a workflow transfer document, to be used by unified ReqMgr2MS.
|
|
277
|
+
"""
|
|
278
|
+
return self._getDataFromMemoryCache('transferinfo/%s' % docName)
|
|
279
|
+
|
|
280
|
+
def postTransferInfo(self, docName, transferInfo):
|
|
281
|
+
"""
|
|
282
|
+
Create a new workflow transfer document
|
|
283
|
+
|
|
284
|
+
:param docName: the name of the document to be created
|
|
285
|
+
:param transferInfo: a dictionary with the document content
|
|
286
|
+
:return: CouchDB response dictionary
|
|
287
|
+
"""
|
|
288
|
+
return self["requests"].post('transferinfo/%s' % docName, transferInfo)[0]['result']
|
|
289
|
+
|
|
290
|
+
def updateTransferInfo(self, docName, content, inPlace=False):
|
|
291
|
+
"""
|
|
292
|
+
Update the corresponding workflow transfer document with the content
|
|
293
|
+
provided, replacing the old one.
|
|
294
|
+
If inPlace is set to True, then a modification of the current
|
|
295
|
+
document is performed, according to the key/value pairs provided.
|
|
296
|
+
:param docName: name of the transfer document in couch
|
|
297
|
+
:param content: a dictionary with the data to be updated
|
|
298
|
+
:param inPlace: a boolean defining whether to perform a replace
|
|
299
|
+
or a update modification
|
|
300
|
+
:return: a boolean with the result of the operation
|
|
301
|
+
"""
|
|
302
|
+
api = 'transferinfo'
|
|
303
|
+
if inPlace:
|
|
304
|
+
resp = self._updateRecords(api, docName, content)
|
|
305
|
+
else:
|
|
306
|
+
resp = self["requests"].put("%s/%s" % (api, docName), content)[0]['result']
|
|
307
|
+
|
|
308
|
+
if resp and resp[0].get("ok", False):
|
|
309
|
+
self["logger"].info("Update in-place: %s for transfer doc: %s was successful.", inPlace, docName)
|
|
310
|
+
return True
|
|
311
|
+
msg = "Failed to update transfer doc: %s in-place: %s. Response: %s" % (docName, inPlace, resp)
|
|
312
|
+
self["logger"].warning(msg)
|
|
313
|
+
return False
|
|
314
|
+
|
|
315
|
+
def updateParentLocks(self, content, docName=None):
|
|
316
|
+
"""
|
|
317
|
+
Update the list of locked parent datasets with the content provided, replacing
|
|
318
|
+
the old document.
|
|
319
|
+
:param content: a dictionary with the data to be updated
|
|
320
|
+
:return: a boolean with the result of the operation
|
|
321
|
+
"""
|
|
322
|
+
api = 'parentlocks'
|
|
323
|
+
if docName:
|
|
324
|
+
resp = self["requests"].put("%s/%s" % (api, docName), content)[0]['result']
|
|
325
|
+
else:
|
|
326
|
+
resp = self["requests"].put("%s" % api, content)[0]['result']
|
|
327
|
+
|
|
328
|
+
if resp and resp[0].get("ok", False):
|
|
329
|
+
self["logger"].info("Parent dataset locks successfully updated.")
|
|
330
|
+
return True
|
|
331
|
+
|
|
332
|
+
self["logger"].warning("Failed to update parent dataset locks. Response: %s", resp)
|
|
333
|
+
return False
|
|
334
|
+
|
|
335
|
+
def getParentLocks(self):
|
|
336
|
+
"""
|
|
337
|
+
get the list of parent locks
|
|
338
|
+
"""
|
|
339
|
+
return self._getDataFromMemoryCache('parentlocks')
|
|
340
|
+
|
|
341
|
+
def deleteConfigDoc(self, docType, docName):
|
|
342
|
+
"""
|
|
343
|
+
Given a document type and a document name, delete it from the
|
|
344
|
+
Couch auxiliary DB.
|
|
345
|
+
:param docType: a string with the document type to be deleted, which
|
|
346
|
+
corresponds to the same API name
|
|
347
|
+
:param docName: the name of the document to be deleted
|
|
348
|
+
:return: response dictionary from the couch operation
|
|
349
|
+
"""
|
|
350
|
+
allowedValues = ('wmagentconfig', 'campaignconfig', 'unifiedconfig', 'transferinfo')
|
|
351
|
+
if docType not in allowedValues:
|
|
352
|
+
msg = "Document type: '%s' not allowed for deletion." % docType
|
|
353
|
+
msg += " Supported documents are: %s" % allowedValues
|
|
354
|
+
self["logger"].warning(msg)
|
|
355
|
+
else:
|
|
356
|
+
return self["requests"].delete('%s/%s' % (docType, docName))[0]['result']
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
AUXDB_AGENT_CONFIG_CACHE = {}
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
# function to check whether agent is should be in draining status.
|
|
363
|
+
def isDrainMode(config):
|
|
364
|
+
"""
|
|
365
|
+
config is loaded from WMAgentConfig in local config
|
|
366
|
+
agentDrainMode is boolean value. (if it is passed update the WMAgentConfig in couchdb)
|
|
367
|
+
"""
|
|
368
|
+
if hasattr(config, "Tier0Feeder"):
|
|
369
|
+
return False
|
|
370
|
+
|
|
371
|
+
global AUXDB_AGENT_CONFIG_CACHE
|
|
372
|
+
|
|
373
|
+
reqMgrAux = ReqMgrAux(config.General.ReqMgr2ServiceURL)
|
|
374
|
+
agentConfig = reqMgrAux.getWMAgentConfig(config.Agent.hostName)
|
|
375
|
+
if "UserDrainMode" in agentConfig and "AgentDrainMode" in agentConfig:
|
|
376
|
+
AUXDB_AGENT_CONFIG_CACHE = agentConfig
|
|
377
|
+
return agentConfig["UserDrainMode"] or agentConfig["AgentDrainMode"]
|
|
378
|
+
# if the cache is empty this will raise Key not exist exception.
|
|
379
|
+
return AUXDB_AGENT_CONFIG_CACHE["UserDrainMode"] or AUXDB_AGENT_CONFIG_CACHE["AgentDrainMode"]
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def listDiskUsageOverThreshold(config, updateDB):
|
|
383
|
+
"""
|
|
384
|
+
check whether disk usage is over threshold,
|
|
385
|
+
return list of disk paths
|
|
386
|
+
if updateDB is True update the aux couch db value.
|
|
387
|
+
This function contains both check an update to avoide multiple db calls.
|
|
388
|
+
"""
|
|
389
|
+
defaultDiskThreshold = 85
|
|
390
|
+
defaultIgnoredDisks = []
|
|
391
|
+
if hasattr(config, "Tier0Feeder"):
|
|
392
|
+
# get the value from config.
|
|
393
|
+
ignoredDisks = getattr(config.AgentStatusWatcher, "ignoreDisks", defaultIgnoredDisks)
|
|
394
|
+
diskUseThreshold = getattr(config.AgentStatusWatcher, "diskUseThreshold", defaultDiskThreshold)
|
|
395
|
+
t0Flag = True
|
|
396
|
+
else:
|
|
397
|
+
reqMgrAux = ReqMgrAux(config.General.ReqMgr2ServiceURL)
|
|
398
|
+
agentConfig = reqMgrAux.getWMAgentConfig(config.Agent.hostName)
|
|
399
|
+
diskUseThreshold = agentConfig.get("DiskUseThreshold", defaultDiskThreshold)
|
|
400
|
+
ignoredDisks = agentConfig.get("IgnoreDisks", defaultIgnoredDisks)
|
|
401
|
+
t0Flag = False
|
|
402
|
+
|
|
403
|
+
# Disk space warning
|
|
404
|
+
diskUseList = diskUse()
|
|
405
|
+
overThresholdDisks = []
|
|
406
|
+
for disk in diskUseList:
|
|
407
|
+
if (float(disk['percent'].strip('%')) >= diskUseThreshold and
|
|
408
|
+
disk['mounted'] not in ignoredDisks):
|
|
409
|
+
overThresholdDisks.append(disk)
|
|
410
|
+
|
|
411
|
+
if updateDB and not t0Flag:
|
|
412
|
+
agentDrainMode = bool(len(overThresholdDisks))
|
|
413
|
+
if agentConfig and (agentDrainMode != agentConfig.get("AgentDrainMode")):
|
|
414
|
+
if agentConfig.get("UserDrainMode") is True:
|
|
415
|
+
logging.info("Agent is already in UserDrainMode: True mode. No need to update.")
|
|
416
|
+
else:
|
|
417
|
+
reqMgrAux.updateWMAgentConfig(config.Agent.hostName, {"AgentDrainMode": agentDrainMode}, inPlace=True)
|
|
418
|
+
|
|
419
|
+
return overThresholdDisks
|
|
File without changes
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
from builtins import str, bytes, object
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from WMCore.Database.CMSCouch import CouchServer, Database
|
|
5
|
+
from WMCore.Lexicon import splitCouchServiceURL, sanitizeURL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RequestDBReader(object):
|
|
9
|
+
def __init__(self, couchURL, couchapp="ReqMgr"):
|
|
10
|
+
# set the connection for local couchDB call
|
|
11
|
+
self._commonInit(couchURL, couchapp)
|
|
12
|
+
|
|
13
|
+
def _commonInit(self, couchURL, couchapp):
|
|
14
|
+
"""
|
|
15
|
+
setting up comon variables for inherited class.
|
|
16
|
+
inherited class should call this in their init function
|
|
17
|
+
"""
|
|
18
|
+
if isinstance(couchURL, Database):
|
|
19
|
+
self.couchDB = couchURL
|
|
20
|
+
self.couchURL = self.couchDB['host']
|
|
21
|
+
self.dbName = self.couchDB.name
|
|
22
|
+
self.couchServer = CouchServer(self.couchURL)
|
|
23
|
+
else:
|
|
24
|
+
# NOTE: starting in CouchDB 3.x, we need to provide the couch credentials in
|
|
25
|
+
# order to be able to write to the database, thus a RequestDBWriter object
|
|
26
|
+
if isinstance(self.__class__, RequestDBReader):
|
|
27
|
+
couchURL = sanitizeURL(couchURL)['url']
|
|
28
|
+
self.couchURL, self.dbName = splitCouchServiceURL(couchURL)
|
|
29
|
+
self.couchServer = CouchServer(self.couchURL)
|
|
30
|
+
self.couchDB = self.couchServer.connectDatabase(self.dbName, False)
|
|
31
|
+
self.couchapp = couchapp
|
|
32
|
+
self.defaultStale = {"stale": "update_after"}
|
|
33
|
+
|
|
34
|
+
def setDefaultStaleOptions(self, options):
|
|
35
|
+
if not options:
|
|
36
|
+
options = {}
|
|
37
|
+
if 'stale' not in options:
|
|
38
|
+
options.update(self.defaultStale)
|
|
39
|
+
return options
|
|
40
|
+
|
|
41
|
+
def _setNoStale(self):
|
|
42
|
+
"""
|
|
43
|
+
Use this only for the unittest
|
|
44
|
+
"""
|
|
45
|
+
self.defaultStale = {}
|
|
46
|
+
|
|
47
|
+
def _getCouchView(self, view, options, keys=None):
|
|
48
|
+
keys = keys or []
|
|
49
|
+
options = self.setDefaultStaleOptions(options)
|
|
50
|
+
|
|
51
|
+
if keys and isinstance(keys, (str, bytes)):
|
|
52
|
+
keys = [keys]
|
|
53
|
+
return self.couchDB.loadView(self.couchapp, view, options, keys)
|
|
54
|
+
|
|
55
|
+
def _filterCouchInfo(self, couchInfo):
|
|
56
|
+
# remove the couch specific information
|
|
57
|
+
for key in ['_rev', '_attachments']:
|
|
58
|
+
if key in couchInfo:
|
|
59
|
+
del couchInfo[key]
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
def _formatCouchData(self, data, key="id", detail=True, filterCouch=True, returnDict=False):
|
|
63
|
+
result = {}
|
|
64
|
+
for row in data['rows']:
|
|
65
|
+
if 'error' in row:
|
|
66
|
+
continue
|
|
67
|
+
if "doc" in row:
|
|
68
|
+
if filterCouch:
|
|
69
|
+
self._filterCouchInfo(row["doc"])
|
|
70
|
+
result[row[key]] = row["doc"]
|
|
71
|
+
else:
|
|
72
|
+
result[row[key]] = row["value"]
|
|
73
|
+
if detail or returnDict:
|
|
74
|
+
return result
|
|
75
|
+
else:
|
|
76
|
+
return list(result)
|
|
77
|
+
|
|
78
|
+
def _getRequestByName(self, requestName, detail):
|
|
79
|
+
"""
|
|
80
|
+
Retrieves a request dictionary from CouchDB
|
|
81
|
+
:param requestName: string with the request name
|
|
82
|
+
:param detail: boolean with False value for retrieving only the
|
|
83
|
+
workflow name, or True for retrieving all its description
|
|
84
|
+
:return: a list with the request name. Or a dictionary with the
|
|
85
|
+
request description if detail=true
|
|
86
|
+
"""
|
|
87
|
+
# this returns a dictionary with the workflow description, or
|
|
88
|
+
# an empty dictionary if nothing is found in CouchDB
|
|
89
|
+
result = self.couchDB.getDoc(requestName)
|
|
90
|
+
if not result:
|
|
91
|
+
return dict()
|
|
92
|
+
if detail:
|
|
93
|
+
result.pop('_attachments', None)
|
|
94
|
+
result.pop('_rev', None)
|
|
95
|
+
return {result['RequestName']: result}
|
|
96
|
+
return [result['RequestName']]
|
|
97
|
+
|
|
98
|
+
def _getRequestByNames(self, requestNames, detail):
|
|
99
|
+
"""
|
|
100
|
+
'status': list of the status
|
|
101
|
+
"""
|
|
102
|
+
options = {}
|
|
103
|
+
options["include_docs"] = detail
|
|
104
|
+
result = self.couchDB.allDocs(options, requestNames)
|
|
105
|
+
return result
|
|
106
|
+
|
|
107
|
+
def _getRequestByStatus(self, statusList, detail, limit, skip):
|
|
108
|
+
"""
|
|
109
|
+
'status': list of the status
|
|
110
|
+
"""
|
|
111
|
+
options = {}
|
|
112
|
+
options["include_docs"] = detail
|
|
113
|
+
|
|
114
|
+
if limit != None:
|
|
115
|
+
options["limit"] = limit
|
|
116
|
+
if skip != None:
|
|
117
|
+
options["skip"] = skip
|
|
118
|
+
keys = statusList
|
|
119
|
+
return self._getCouchView("bystatus", options, keys)
|
|
120
|
+
|
|
121
|
+
def _getRequestByStatusAndStartTime(self, status, detail, startTime):
|
|
122
|
+
timeNow = int(time.time())
|
|
123
|
+
options = {}
|
|
124
|
+
options["include_docs"] = detail
|
|
125
|
+
options["startkey"] = [status, startTime]
|
|
126
|
+
options["endkey"] = [status, timeNow]
|
|
127
|
+
options["descending"] = False
|
|
128
|
+
|
|
129
|
+
return self._getCouchView("bystatusandtime", options)
|
|
130
|
+
|
|
131
|
+
def _getRequestByStatusAndEndTime(self, status, detail, endTime):
|
|
132
|
+
"""
|
|
133
|
+
'status': is the status of the workflow
|
|
134
|
+
'endTime': unix timestamp for end time
|
|
135
|
+
"""
|
|
136
|
+
options = {}
|
|
137
|
+
options["include_docs"] = detail
|
|
138
|
+
options["startkey"] = [status, 0]
|
|
139
|
+
options["endkey"] = [status, endTime]
|
|
140
|
+
options["descending"] = False
|
|
141
|
+
|
|
142
|
+
return self._getCouchView("bystatusandtime", options)
|
|
143
|
+
|
|
144
|
+
def _getRequestByTeamAndStatus(self, team, status, limit):
|
|
145
|
+
"""
|
|
146
|
+
'status': is the status of the workflow
|
|
147
|
+
'startTime': unix timestamp for start time
|
|
148
|
+
"""
|
|
149
|
+
options = {}
|
|
150
|
+
if limit:
|
|
151
|
+
options["limit"] = limit
|
|
152
|
+
if team and status:
|
|
153
|
+
options["key"] = [team, status]
|
|
154
|
+
elif team and not status:
|
|
155
|
+
options["startkey"] = [team]
|
|
156
|
+
options["endkey"] = [team, status] # status = {}
|
|
157
|
+
|
|
158
|
+
return self._getCouchView("byteamandstatus", options)
|
|
159
|
+
|
|
160
|
+
def _getAllDocsByIDs(self, ids, include_docs=True):
|
|
161
|
+
"""
|
|
162
|
+
keys is [id, ....]
|
|
163
|
+
returns document
|
|
164
|
+
"""
|
|
165
|
+
if len(ids) == 0:
|
|
166
|
+
return []
|
|
167
|
+
options = {}
|
|
168
|
+
options["include_docs"] = include_docs
|
|
169
|
+
result = self.couchDB.allDocs(options, ids)
|
|
170
|
+
|
|
171
|
+
return result
|
|
172
|
+
|
|
173
|
+
def getDBInstance(self):
|
|
174
|
+
return self.couchDB
|
|
175
|
+
|
|
176
|
+
def getRequestByNames(self, requestNames, detail=True):
|
|
177
|
+
if len(requestNames) == 0:
|
|
178
|
+
return {}
|
|
179
|
+
if isinstance(requestNames, list) and len(requestNames) == 1:
|
|
180
|
+
requestNames = requestNames[0]
|
|
181
|
+
|
|
182
|
+
if isinstance(requestNames, (str, bytes)):
|
|
183
|
+
requestInfo = self._getRequestByName(requestNames, detail=detail)
|
|
184
|
+
else:
|
|
185
|
+
requestInfo = self._getRequestByNames(requestNames, detail=detail)
|
|
186
|
+
requestInfo = self._formatCouchData(requestInfo, detail=detail)
|
|
187
|
+
return requestInfo
|
|
188
|
+
|
|
189
|
+
def getRequestByStatus(self, statusList, detail=False, limit=None, skip=None):
|
|
190
|
+
|
|
191
|
+
data = self._getRequestByStatus(statusList, detail, limit, skip)
|
|
192
|
+
requestInfo = self._formatCouchData(data, detail=detail)
|
|
193
|
+
|
|
194
|
+
return requestInfo
|
|
195
|
+
|
|
196
|
+
def getRequestByStatusAndStartTime(self, status, detail=False, startTime=0):
|
|
197
|
+
"""
|
|
198
|
+
Query for requests that are in a specific status since startTime.
|
|
199
|
+
:param status: string with the workflow status
|
|
200
|
+
:param detail: boolean flag used to return doc content or not
|
|
201
|
+
:param startTime: unix start timestamp for your query
|
|
202
|
+
:return: a list of request names
|
|
203
|
+
"""
|
|
204
|
+
if startTime == 0:
|
|
205
|
+
data = self._getRequestByStatus([status], detail, limit=None, skip=None)
|
|
206
|
+
else:
|
|
207
|
+
data = self._getRequestByStatusAndStartTime(status, detail, startTime)
|
|
208
|
+
|
|
209
|
+
requestInfo = self._formatCouchData(data, detail=detail)
|
|
210
|
+
return requestInfo
|
|
211
|
+
|
|
212
|
+
def getRequestByStatusAndEndTime(self, status, detail=False, endTime=0):
|
|
213
|
+
"""
|
|
214
|
+
Query for requests that are in a specific status until endTime.
|
|
215
|
+
:param status: string with the workflow status
|
|
216
|
+
:param detail: boolean flag used to return doc content or not
|
|
217
|
+
:param endTime: unix end timestamp for your query
|
|
218
|
+
:return: a list of request names
|
|
219
|
+
"""
|
|
220
|
+
if endTime == 0:
|
|
221
|
+
data = self._getRequestByStatus([status], detail, limit=None, skip=None)
|
|
222
|
+
else:
|
|
223
|
+
data = self._getRequestByStatusAndEndTime(status, detail, endTime)
|
|
224
|
+
|
|
225
|
+
requestInfo = self._formatCouchData(data, detail=detail)
|
|
226
|
+
return requestInfo
|
|
227
|
+
|
|
228
|
+
def getRequestByTeamAndStatus(self, team, status, detail=False, limit=None):
|
|
229
|
+
"""
|
|
230
|
+
'team': team name in which the workflow was assigned to.
|
|
231
|
+
'status': a single status string.
|
|
232
|
+
"""
|
|
233
|
+
if team and status:
|
|
234
|
+
data = self._getRequestByTeamAndStatus(team, status, limit)
|
|
235
|
+
elif team and not status:
|
|
236
|
+
data = self._getRequestByTeamAndStatus(team, status={}, limit=limit)
|
|
237
|
+
elif not team and not status:
|
|
238
|
+
data = self._getRequestByTeamAndStatus(team={}, status={}, limit=limit)
|
|
239
|
+
else:
|
|
240
|
+
# nothing we can do with status only
|
|
241
|
+
return
|
|
242
|
+
|
|
243
|
+
requestInfo = self._formatCouchData(data, detail=detail)
|
|
244
|
+
return requestInfo
|
|
245
|
+
|
|
246
|
+
def getRequestByCouchView(self, view, options, keys=None, returnDict=True):
|
|
247
|
+
keys = keys or []
|
|
248
|
+
options.setdefault("include_docs", True)
|
|
249
|
+
data = self._getCouchView(view, options, keys)
|
|
250
|
+
requestInfo = self._formatCouchData(data, returnDict=returnDict)
|
|
251
|
+
return requestInfo
|
|
252
|
+
|
|
253
|
+
def getStatusAndTypeByRequest(self, requestNames):
|
|
254
|
+
if isinstance(requestNames, (str, bytes)):
|
|
255
|
+
requestNames = [requestNames]
|
|
256
|
+
if len(requestNames) == 0:
|
|
257
|
+
return {}
|
|
258
|
+
data = self._getCouchView("byrequest", {}, requestNames)
|
|
259
|
+
requestInfo = self._formatCouchData(data, returnDict=True)
|
|
260
|
+
return requestInfo
|
|
261
|
+
|
|
262
|
+
def getStepChainDatasetParentageByStatus(self, status):
|
|
263
|
+
options = {}
|
|
264
|
+
options["key"] = [False, status]
|
|
265
|
+
data = self._getCouchView("byparentageflag", options)
|
|
266
|
+
datasetParentageInfo = self._formatCouchData(data, returnDict=True)
|
|
267
|
+
return datasetParentageInfo
|