wmglobalqueue 2.4.5.1__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.
- Utils/CPMetrics.py +270 -0
- Utils/CertTools.py +100 -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/ProcFS.py +112 -0
- Utils/ProcessStats.py +194 -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 +318 -0
- Utils/__init__.py +11 -0
- Utils/wmcoreDTools.py +707 -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 +659 -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 +1430 -0
- WMCore/Database/ConfigDBMap.py +29 -0
- WMCore/Database/CouchMonitoring.py +450 -0
- WMCore/Database/CouchUtils.py +118 -0
- WMCore/Database/DBCore.py +198 -0
- WMCore/Database/DBCreator.py +113 -0
- WMCore/Database/DBExceptionHandler.py +59 -0
- WMCore/Database/DBFactory.py +117 -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 +636 -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 +112 -0
- WMCore/Services/DBS/DBSReader.py +23 -0
- WMCore/Services/DBS/DBSUtils.py +166 -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/__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 +1290 -0
- WMCore/Services/Rucio/RucioUtils.py +74 -0
- WMCore/Services/Rucio/__init__.py +0 -0
- WMCore/Services/RucioConMon/RucioConMon.py +121 -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 +377 -0
- WMCore/WMLogging.py +104 -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 +1997 -0
- WMCore/WMSpec/WMWorkload.py +2288 -0
- WMCore/WMSpec/WMWorkloadTools.py +382 -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.4.5.1.data/data/bin/wmc-dist-patch +15 -0
- wmglobalqueue-2.4.5.1.data/data/bin/wmc-dist-unpatch +8 -0
- wmglobalqueue-2.4.5.1.data/data/bin/wmc-httpd +3 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/.couchapprc +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/README.md +40 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/index.html +264 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/ElementInfoByWorkflow.js +96 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/StuckElementInfo.js +57 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/WorkloadInfoTable.js +80 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/dataTable.js +70 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/namespace.js +23 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/style/main.css +75 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/couchapp.json +4 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/childQueueFilter.js +13 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/filterDeletedDocs.js +3 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/queueFilter.js +11 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/language +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/mustache.js +333 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/validate.js +27 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/workqueue_utils.js +61 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/elementsDetail.js +28 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/filter.js +86 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/stuckElements.js +38 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/workRestrictions.js +153 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/workflowSummary.js +28 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/rewrites.json +73 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/shows/redirect.js +23 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/shows/status.js +40 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/ElementSummaryByWorkflow.html +27 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/StuckElementSummary.html +26 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/TaskStatus.html +23 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/WorkflowSummary.html +27 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/workqueue-common-lib.html +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib-remote.html +16 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib.html +18 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/updates/in-place.js +50 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/validate_doc_update.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.couch.app.js +235 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.pathbinder.js +173 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeData/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeParentData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeParentData/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activePileupData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activePileupData/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/analyticsData/map.js +11 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/analyticsData/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/availableByPriority/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/conflicts/map.js +5 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elements/map.js +5 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByParent/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByParentData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByPileupData/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByStatus/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsBySubscription/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/map.js +8 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/reduce.js +3 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsDetailByWorkflowAndStatus/map.js +26 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/map.js +10 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByRequest/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByRequest/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatus/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatus/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/openRequests/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/recent-items/map.js +5 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/reduce.js +1 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/specsByWorkflow/map.js +5 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/stuckElements/map.js +38 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/map.js +12 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/reduce.js +3 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrl/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrl/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/map.js +6 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/reduce.js +2 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/workflowSummary/map.js +9 -0
- wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/workflowSummary/reduce.js +10 -0
- wmglobalqueue-2.4.5.1.dist-info/METADATA +26 -0
- wmglobalqueue-2.4.5.1.dist-info/RECORD +347 -0
- wmglobalqueue-2.4.5.1.dist-info/WHEEL +5 -0
- wmglobalqueue-2.4.5.1.dist-info/licenses/LICENSE +202 -0
- wmglobalqueue-2.4.5.1.dist-info/licenses/NOTICE +16 -0
- wmglobalqueue-2.4.5.1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Basic interface to HTTPS requests using ssl object managers, for python >= 2.7.9.
|
|
4
|
+
See usage example in:
|
|
5
|
+
src/python/WMCore/WMSpec/Steps/Executors/DQMUpload.py
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import print_function, division
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
import ssl
|
|
11
|
+
try:
|
|
12
|
+
# python2
|
|
13
|
+
import urllib2
|
|
14
|
+
import httplib
|
|
15
|
+
HTTPSHandler = urllib2.HTTPSHandler
|
|
16
|
+
HTTPSConnection = httplib.HTTPSConnection
|
|
17
|
+
except:
|
|
18
|
+
# python3
|
|
19
|
+
import urllib.request
|
|
20
|
+
import http.client
|
|
21
|
+
HTTPSHandler = urllib.request.HTTPSHandler
|
|
22
|
+
HTTPSConnection = http.client.HTTPSConnection
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class HTTPSAuthHandler(HTTPSHandler):
|
|
26
|
+
"""
|
|
27
|
+
HTTPS authentication class to provide a ssl context with the certificates.
|
|
28
|
+
"""
|
|
29
|
+
def __init__(self, key=None, cert=None, capath='/etc/grid-security/certificates/', level=0):
|
|
30
|
+
self.logger = logging.getLogger(__name__)
|
|
31
|
+
if cert:
|
|
32
|
+
# then create a default ssl context manager to carry the credentials.
|
|
33
|
+
# It also loads the default CA certificates
|
|
34
|
+
self.ctx = ssl.create_default_context()
|
|
35
|
+
self.ctx.load_cert_chain(cert, keyfile=key)
|
|
36
|
+
self.ctx.load_verify_locations(None, capath)
|
|
37
|
+
|
|
38
|
+
self.logger.info("Found %d default trusted CA certificates.", len(self.ctx.get_ca_certs()))
|
|
39
|
+
### DEBUG start ###
|
|
40
|
+
#for ca in self.ctx.get_ca_certs():
|
|
41
|
+
# if 'CERN' in str(ca['subject']):
|
|
42
|
+
# print(" %s" % str(ca['subject']))
|
|
43
|
+
### DEBUG end ###
|
|
44
|
+
self.logger.info("SSL context manager created with the following settings:")
|
|
45
|
+
self.logger.info(" check_hostname : %s", self.ctx.check_hostname) # default to True
|
|
46
|
+
self.logger.info(" options : %s", self.ctx.options) # default to 2197947391
|
|
47
|
+
self.logger.info(" protocol : %s", self.ctx.protocol) # default to 2 (PROTOCOL_SSLv23)
|
|
48
|
+
self.logger.info(" verify_flags : %s", self.ctx.verify_flags) # default to 0 (VERIFY_DEFAULT)
|
|
49
|
+
self.logger.info(" verify_mode : %s", self.ctx.verify_mode) # default to 2 (CERT_REQUIRED)
|
|
50
|
+
HTTPSHandler.__init__(self, debuglevel=level, context=self.ctx)
|
|
51
|
+
else:
|
|
52
|
+
self.logger.info("Certificate not provided for HTTPSHandler")
|
|
53
|
+
HTTPSHandler.__init__(self, debuglevel=level)
|
|
54
|
+
|
|
55
|
+
def get_connection(self, host, **kwargs):
|
|
56
|
+
if self.ctx:
|
|
57
|
+
return HTTPSConnection(host, context=self.ctx, **kwargs)
|
|
58
|
+
return HTTPSConnection(host)
|
|
59
|
+
|
|
60
|
+
def https_open(self, req):
|
|
61
|
+
"""
|
|
62
|
+
Overwrite the default https_open.
|
|
63
|
+
"""
|
|
64
|
+
self.logger.debug("%s method to %s", req.get_method(), req.get_full_url())
|
|
65
|
+
self.logger.debug(" with the following headers: %s", req.headers)
|
|
66
|
+
return self.do_open(self.get_connection, req)
|
|
File without changes
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
LogDB provides functionality to post/search messages into LogDB.
|
|
4
|
+
https://github.com/dmwm/WMCore/issues/5705
|
|
5
|
+
"""
|
|
6
|
+
# futures
|
|
7
|
+
from builtins import object
|
|
8
|
+
from future.utils import viewitems
|
|
9
|
+
|
|
10
|
+
from future import standard_library
|
|
11
|
+
standard_library.install_aliases()
|
|
12
|
+
|
|
13
|
+
# standard modules
|
|
14
|
+
import logging
|
|
15
|
+
import re
|
|
16
|
+
import threading
|
|
17
|
+
from collections import defaultdict
|
|
18
|
+
from http.client import HTTPException
|
|
19
|
+
|
|
20
|
+
# project modules
|
|
21
|
+
from WMCore.Lexicon import splitCouchServiceURL
|
|
22
|
+
from WMCore.Services.LogDB.LogDBBackend import LogDBBackend
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def getLogDBInstanceFromThread():
|
|
26
|
+
"""This function only gets to call when LogDB is instantiated before hand
|
|
27
|
+
All the WMComponentWorkers instatntiate LogDB automatically
|
|
28
|
+
"""
|
|
29
|
+
myThread = threading.currentThread()
|
|
30
|
+
if not hasattr(myThread, "logdbClient") or not isinstance(myThread.logdbClient, LogDB):
|
|
31
|
+
# logdb is not set do anything
|
|
32
|
+
return None
|
|
33
|
+
return myThread.logdbClient
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class LogDB(object):
|
|
37
|
+
"""
|
|
38
|
+
_LogDB_
|
|
39
|
+
|
|
40
|
+
LogDB object - interface to LogDB functionality.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, url, identifier, logger=None, **kwds):
|
|
44
|
+
self.logger = logger if logger else logging.getLogger()
|
|
45
|
+
self.url = url if url else 'https://cmsweb.cern.ch/couchdb/wmstats_logdb'
|
|
46
|
+
self.identifier = identifier if identifier else 'unknown'
|
|
47
|
+
self.default_user = "HEARTBEAT"
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
self.thread_name = kwds.pop('thread_name')
|
|
51
|
+
except KeyError:
|
|
52
|
+
self.thread_name = threading.currentThread().getName()
|
|
53
|
+
|
|
54
|
+
self.user_pat = re.compile(r'^/[a-zA-Z][a-zA-Z0-9/\=\s()\']*\=[a-zA-Z0-9/\=\.\-_/#:\s\']*$')
|
|
55
|
+
self.agent = 0 if self.user_pat.match(self.identifier) else 1
|
|
56
|
+
couch_url, db_name = splitCouchServiceURL(self.url)
|
|
57
|
+
self.backend = LogDBBackend(couch_url, db_name, identifier,
|
|
58
|
+
self.thread_name, agent=self.agent, **kwds)
|
|
59
|
+
self.logger.info(self)
|
|
60
|
+
|
|
61
|
+
def __repr__(self):
|
|
62
|
+
"Return representation for class"
|
|
63
|
+
return "<LogDB(url=%s, identifier=%s, agent=%d)>" \
|
|
64
|
+
% (self.url, self.identifier, self.agent)
|
|
65
|
+
|
|
66
|
+
def post(self, request=None, msg="", mtype="comment"):
|
|
67
|
+
"""Post new entry into LogDB for given request"""
|
|
68
|
+
res = 'post-error'
|
|
69
|
+
try:
|
|
70
|
+
if request is None:
|
|
71
|
+
request = self.default_user
|
|
72
|
+
if self.user_pat.match(self.identifier):
|
|
73
|
+
res = self.backend.user_update(request, msg, mtype)
|
|
74
|
+
else:
|
|
75
|
+
res = self.backend.agent_update(request, msg, mtype)
|
|
76
|
+
except HTTPException as ex:
|
|
77
|
+
msg = "Failed to post doc to LogDB. Reason: %s, status: %s" % (ex.reason, ex.status)
|
|
78
|
+
self.logger.error(msg)
|
|
79
|
+
except Exception as exc:
|
|
80
|
+
self.logger.error("LogDBBackend post API failed, error=%s", str(exc))
|
|
81
|
+
self.logger.debug("LogDB post request, res=%s", res)
|
|
82
|
+
return res
|
|
83
|
+
|
|
84
|
+
def get(self, request=None, mtype=None):
|
|
85
|
+
"""Retrieve all entries from LogDB for given request"""
|
|
86
|
+
res = []
|
|
87
|
+
try:
|
|
88
|
+
if request is None:
|
|
89
|
+
request = self.default_user
|
|
90
|
+
if self.user_pat.match(self.identifier):
|
|
91
|
+
agent = False
|
|
92
|
+
else:
|
|
93
|
+
agent = True
|
|
94
|
+
for row in self.backend.get(request, mtype, agent=agent).get('rows', []):
|
|
95
|
+
request = row['doc']['request']
|
|
96
|
+
identifier = row['doc']['identifier']
|
|
97
|
+
thr = row['doc']['thr']
|
|
98
|
+
mtype = row['doc']['type']
|
|
99
|
+
for rec in row['doc']['messages']:
|
|
100
|
+
rec.update({'request': request, 'identifier': identifier, 'thr': thr, 'type': mtype})
|
|
101
|
+
res.append(rec)
|
|
102
|
+
except HTTPException as ex:
|
|
103
|
+
msg = "Failed to get doc from LogDB. Reason: %s, status: %s" % (ex.reason, ex.status)
|
|
104
|
+
self.logger.error(msg)
|
|
105
|
+
res = 'get-error'
|
|
106
|
+
except Exception as exc:
|
|
107
|
+
self.logger.error("LogDBBackend get API failed, error=%s", str(exc))
|
|
108
|
+
res = 'get-error'
|
|
109
|
+
self.logger.debug("LogDB get request, res=%s", res)
|
|
110
|
+
return res
|
|
111
|
+
|
|
112
|
+
def get_all_requests(self):
|
|
113
|
+
"""Retrieve all entries from LogDB for given request"""
|
|
114
|
+
try:
|
|
115
|
+
results = self.backend.get_all_requests()
|
|
116
|
+
res = []
|
|
117
|
+
for row in results['rows']:
|
|
118
|
+
res.append(row["key"])
|
|
119
|
+
except Exception as exc:
|
|
120
|
+
self.logger.error("LogDBBackend get_all_requests API failed, error=%s", str(exc))
|
|
121
|
+
res = 'get-error'
|
|
122
|
+
self.logger.debug("LogDB get_all_requests request, res=%s", res)
|
|
123
|
+
return res
|
|
124
|
+
|
|
125
|
+
def delete(self, request=None, mtype=None, this_thread=False, agent=True):
|
|
126
|
+
"""
|
|
127
|
+
Delete entry in LogDB for given request
|
|
128
|
+
if mtype == None - delete all the log for that request
|
|
129
|
+
mtype != None - only delete specified mtype
|
|
130
|
+
"""
|
|
131
|
+
res = 'delete-error'
|
|
132
|
+
try:
|
|
133
|
+
if request is None:
|
|
134
|
+
request = self.default_user
|
|
135
|
+
res = self.backend.delete(request, mtype, this_thread, agent)
|
|
136
|
+
except HTTPException as ex:
|
|
137
|
+
msg = "Failed to delete doc in LogDB. Reason: %s, status: %s" % (ex.reason, ex.status)
|
|
138
|
+
self.logger.error(msg)
|
|
139
|
+
except Exception as ex:
|
|
140
|
+
self.logger.error("LogDBBackend delete API failed, error=%s", str(ex))
|
|
141
|
+
self.logger.debug("LogDB delete request, res=%s", res)
|
|
142
|
+
return res
|
|
143
|
+
|
|
144
|
+
def cleanup(self, thr, backend='local'):
|
|
145
|
+
"""Clean-up back-end LogDB"""
|
|
146
|
+
docs = []
|
|
147
|
+
try:
|
|
148
|
+
docs = self.backend.cleanup(thr)
|
|
149
|
+
except Exception as exc:
|
|
150
|
+
self.logger.error('LogDBBackend cleanup API failed, backend=%s, error=%s', backend, str(exc))
|
|
151
|
+
return docs
|
|
152
|
+
|
|
153
|
+
def heartbeat_report(self):
|
|
154
|
+
report = defaultdict(dict)
|
|
155
|
+
if self.user_pat.match(self.identifier):
|
|
156
|
+
self.logger.error("User %s: doesn't allow this function", self.identifier)
|
|
157
|
+
return report
|
|
158
|
+
|
|
159
|
+
for row in self.backend.get(self.default_user, None, agent=True).get('rows', []):
|
|
160
|
+
identifier = row['doc']['identifier']
|
|
161
|
+
# wmstats thread can run in multiple boxed.
|
|
162
|
+
if self.identifier == identifier or identifier.startswith(self.identifier):
|
|
163
|
+
# this will handle wmstats DataCacheUpdate thread with multiple machine
|
|
164
|
+
postfix = identifier.replace(self.identifier, "")
|
|
165
|
+
thr = "%s%s" % (row['doc']['thr'], postfix)
|
|
166
|
+
mtype = row['doc']['type']
|
|
167
|
+
ts = row['doc']['messages'][-1]['ts']
|
|
168
|
+
msg = row['doc']['messages'][-1]['msg']
|
|
169
|
+
if (thr in report) and ('ts' in report[thr]) and ts <= report[thr]['ts']:
|
|
170
|
+
continue
|
|
171
|
+
else:
|
|
172
|
+
report[thr]['type'] = mtype
|
|
173
|
+
report[thr]['msg'] = msg
|
|
174
|
+
report[thr]['ts'] = ts
|
|
175
|
+
return report
|
|
176
|
+
|
|
177
|
+
def _append_down_component_detail(self, report, thr, msg, ts=0, state="error"):
|
|
178
|
+
report['down_components'].append(thr)
|
|
179
|
+
detail = {'name': thr, 'worker_name': thr, 'state': state,
|
|
180
|
+
'last_error': ts, 'error_message': msg,
|
|
181
|
+
'pid': 'N/A'}
|
|
182
|
+
report['down_component_detail'].append(detail)
|
|
183
|
+
return
|
|
184
|
+
|
|
185
|
+
def wmstats_down_components_report(self, thread_list):
|
|
186
|
+
report = {}
|
|
187
|
+
report['down_components'] = []
|
|
188
|
+
report['down_component_detail'] = []
|
|
189
|
+
|
|
190
|
+
hbinfo = self.heartbeat_report()
|
|
191
|
+
for thr in thread_list:
|
|
192
|
+
# skip DataCacheUpdate thread. It will have multiple with post fix.
|
|
193
|
+
# i.e. DataCacheUpdate-vocms111
|
|
194
|
+
# TODO, need a better way to check
|
|
195
|
+
if thr != "DataCacheUpdate" and thr not in hbinfo:
|
|
196
|
+
self._append_down_component_detail(report, thr, "Thread not running")
|
|
197
|
+
|
|
198
|
+
for thr, info in viewitems(hbinfo):
|
|
199
|
+
if info['type'] == 'agent-error':
|
|
200
|
+
self._append_down_component_detail(report, thr, info['msg'], info['ts'])
|
|
201
|
+
return report
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
LogDBBackend
|
|
4
|
+
|
|
5
|
+
Interface to LogDB persistent storage
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from builtins import object, bytes
|
|
9
|
+
|
|
10
|
+
from Utils.PythonVersion import PY3
|
|
11
|
+
from Utils.Utilities import encodeUnicodeToBytes, encodeUnicodeToBytesConditional
|
|
12
|
+
|
|
13
|
+
# system modules
|
|
14
|
+
import datetime
|
|
15
|
+
import hashlib
|
|
16
|
+
import time
|
|
17
|
+
|
|
18
|
+
# WMCore modules
|
|
19
|
+
from WMCore.Database.CMSCouch import CouchServer, CouchNotFoundError
|
|
20
|
+
from WMCore.Services.LogDB.LogDBExceptions import LogDBError
|
|
21
|
+
|
|
22
|
+
# define full list of supported LogDB types
|
|
23
|
+
LOGDB_MSG_TYPES = ['info', 'error', 'warning', 'comment']
|
|
24
|
+
|
|
25
|
+
def gen_hash(key):
|
|
26
|
+
"Generate hash for given key"
|
|
27
|
+
key = encodeUnicodeToBytes(key) # if key is not unicode, then it is not changed
|
|
28
|
+
if not isinstance(key, bytes):
|
|
29
|
+
raise NotImplementedError
|
|
30
|
+
keyhash = hashlib.md5()
|
|
31
|
+
keyhash.update(encodeUnicodeToBytesConditional(key, condition=PY3))
|
|
32
|
+
return keyhash.hexdigest()
|
|
33
|
+
|
|
34
|
+
def tstamp():
|
|
35
|
+
"Return timestamp with microseconds"
|
|
36
|
+
now = datetime.datetime.now()
|
|
37
|
+
base = str(time.mktime(now.timetuple())).split('.')[0]
|
|
38
|
+
ctime = '%s.%s' % (base, now.microsecond)
|
|
39
|
+
return float(ctime)
|
|
40
|
+
|
|
41
|
+
def clean_entry(doc):
|
|
42
|
+
"""Clean document from CouchDB attributes"""
|
|
43
|
+
for attr in ['_rev', '_id']:
|
|
44
|
+
if attr in doc:
|
|
45
|
+
del doc[attr]
|
|
46
|
+
return doc
|
|
47
|
+
|
|
48
|
+
class LogDBBackend(object):
|
|
49
|
+
"""
|
|
50
|
+
Represents persistent storage for LogDB
|
|
51
|
+
"""
|
|
52
|
+
def __init__(self, db_url, db_name, identifier, thread_name, **kwds):
|
|
53
|
+
self.db_url = db_url
|
|
54
|
+
self.server = CouchServer(db_url)
|
|
55
|
+
self.db_name = db_name
|
|
56
|
+
self.dbid = identifier
|
|
57
|
+
self.thread_name = thread_name
|
|
58
|
+
self.agent = kwds.get('agent', 0)
|
|
59
|
+
self.db = self.server.connectDatabase(db_name, create=False)
|
|
60
|
+
self.design = 'LogDB' # name of design document
|
|
61
|
+
self.view = 'requests' # name of view to look-up requests
|
|
62
|
+
self.tsview = 'tstamp' # name of tsview to look-up requests
|
|
63
|
+
self.threadview = 'logByRequestAndThread'
|
|
64
|
+
self.requestview = 'logByRequest'
|
|
65
|
+
|
|
66
|
+
def deleteDatabase(self):
|
|
67
|
+
"""Delete back-end database"""
|
|
68
|
+
if self.db_name in self.server.listDatabases():
|
|
69
|
+
self.server.deleteDatabase(self.db_name)
|
|
70
|
+
|
|
71
|
+
def check(self, request, mtype=None):
|
|
72
|
+
"""Check that given request name is valid"""
|
|
73
|
+
# TODO: we may add some logic to check request name, etc.
|
|
74
|
+
if not request:
|
|
75
|
+
raise LogDBError("Request name is empty")
|
|
76
|
+
if mtype and mtype not in LOGDB_MSG_TYPES:
|
|
77
|
+
raise LogDBError("Unsupported message type: '%s', supported types %s" \
|
|
78
|
+
% (mtype, LOGDB_MSG_TYPES))
|
|
79
|
+
|
|
80
|
+
def docid(self, request, mtype):
|
|
81
|
+
"""Generate doc id, we use double dash to avoid dashes from thread names"""
|
|
82
|
+
return gen_hash('--'.join((request, self.dbid, self.thread_name, mtype)))
|
|
83
|
+
|
|
84
|
+
def prefix(self, mtype):
|
|
85
|
+
"""Generate agent specific prefix for given message type"""
|
|
86
|
+
if self.agent:
|
|
87
|
+
# we add prefix for agent messages, all others will not have this index
|
|
88
|
+
mtype = 'agent-%s' % mtype
|
|
89
|
+
return mtype
|
|
90
|
+
|
|
91
|
+
def agent_update(self, request, msg='', mtype="info"):
|
|
92
|
+
"""Update agent info in LogDB for given request"""
|
|
93
|
+
self.check(request, mtype)
|
|
94
|
+
mtype = self.prefix(mtype)
|
|
95
|
+
rec = {"ts":tstamp(), "msg":msg}
|
|
96
|
+
doc = {"_id": self.docid(request, mtype), "messages": [rec],
|
|
97
|
+
"request":request, "identifier":self.dbid,
|
|
98
|
+
"thr":self.thread_name, "type":mtype}
|
|
99
|
+
try:
|
|
100
|
+
exist_doc = self.db.document(doc["_id"])
|
|
101
|
+
doc["_rev"] = exist_doc["_rev"]
|
|
102
|
+
except CouchNotFoundError:
|
|
103
|
+
# this means document is not exist so we will just insert
|
|
104
|
+
pass
|
|
105
|
+
finally:
|
|
106
|
+
res = self.db.commitOne(doc)
|
|
107
|
+
return res
|
|
108
|
+
|
|
109
|
+
def user_update(self, request, msg, mtype='comment'):
|
|
110
|
+
"""Update user info in LogDB for given request"""
|
|
111
|
+
rec = {"ts":tstamp(), "msg":msg}
|
|
112
|
+
doc = {"_id": self.docid(request, mtype), "messages": [rec],
|
|
113
|
+
"request":request, "identifier":self.dbid,
|
|
114
|
+
"thr":self.thread_name, "type":mtype}
|
|
115
|
+
try:
|
|
116
|
+
exist_doc = self.db.document(doc["_id"])
|
|
117
|
+
doc["_rev"] = exist_doc["_rev"]
|
|
118
|
+
doc["messages"] += exist_doc["messages"]
|
|
119
|
+
except CouchNotFoundError:
|
|
120
|
+
# this means document is not exist so we will just insert
|
|
121
|
+
pass
|
|
122
|
+
finally:
|
|
123
|
+
res = self.db.commitOne(doc)
|
|
124
|
+
return res
|
|
125
|
+
|
|
126
|
+
def get(self, request, mtype=None, detail=True, agent=True):
|
|
127
|
+
"""Retrieve all entries from LogDB for given request"""
|
|
128
|
+
self.check(request, mtype)
|
|
129
|
+
if agent and mtype:
|
|
130
|
+
mtype = self.prefix(mtype)
|
|
131
|
+
options = {'reduce':False}
|
|
132
|
+
if mtype:
|
|
133
|
+
keys = [[request, mtype]]
|
|
134
|
+
else:
|
|
135
|
+
keys=[]
|
|
136
|
+
options.update({'startkey': [request], 'endkey':[request, {}]})
|
|
137
|
+
if detail:
|
|
138
|
+
options.update({'include_docs': True})
|
|
139
|
+
docs = self.db.loadView(self.design, self.view, options, keys=keys)
|
|
140
|
+
return docs
|
|
141
|
+
|
|
142
|
+
def get_by_thread(self, request, mtype='error', detail=False, agent=True):
|
|
143
|
+
self.check(request, mtype)
|
|
144
|
+
if agent and mtype:
|
|
145
|
+
mtype = self.prefix(mtype)
|
|
146
|
+
keys = [[request, self.dbid, self.thread_name, mtype]]
|
|
147
|
+
options = {'reduce':False}
|
|
148
|
+
if detail:
|
|
149
|
+
options.update({'include_docs': True})
|
|
150
|
+
docs = self.db.loadView(self.design, self.threadview, options, keys)
|
|
151
|
+
return docs
|
|
152
|
+
|
|
153
|
+
def get_by_request(self, request):
|
|
154
|
+
keys = [request]
|
|
155
|
+
options = {'reduce':False}
|
|
156
|
+
docs = self.db.loadView(self.design, self.requestview, options, keys)
|
|
157
|
+
return docs
|
|
158
|
+
|
|
159
|
+
def get_all_requests(self):
|
|
160
|
+
"""Retrieve all entries from LogDB"""
|
|
161
|
+
options = {'reduce':True, 'group_level':1}
|
|
162
|
+
docs = self.db.loadView(self.design, self.view, options)
|
|
163
|
+
return docs
|
|
164
|
+
|
|
165
|
+
def delete(self, request, mtype=None, this_thread=False, agent=True):
|
|
166
|
+
"""Delete entry in LogDB for given request"""
|
|
167
|
+
if mtype:
|
|
168
|
+
self.check(request, mtype)
|
|
169
|
+
else:
|
|
170
|
+
self.check(request)
|
|
171
|
+
if this_thread:
|
|
172
|
+
docs = self.get_by_thread(request, mtype=mtype, detail=False, agent=agent)
|
|
173
|
+
else:
|
|
174
|
+
docs = self.get(request, mtype=mtype, detail=False, agent=agent)
|
|
175
|
+
ids = [r['id'] for r in docs.get('rows', [])]
|
|
176
|
+
res = self.db.bulkDeleteByIDs(ids)
|
|
177
|
+
return res
|
|
178
|
+
|
|
179
|
+
def cleanup(self, thr):
|
|
180
|
+
"""
|
|
181
|
+
Clean-up docs older then given threshold (thr should be specified in seconds).
|
|
182
|
+
This is done via tstamp view end endkey, e.g.
|
|
183
|
+
curl "http://127.0.0.1:5984/logdb/_design/LogDB/_view/tstamp?endkey=1427912282"
|
|
184
|
+
"""
|
|
185
|
+
cutoff = int(round(time.time()-thr))
|
|
186
|
+
#docs = self.db.allDocs() # may need another view to look-up old docs
|
|
187
|
+
spec = {'endkey':cutoff, 'reduce':False}
|
|
188
|
+
docs = self.db.loadView(self.design, self.tsview, spec)
|
|
189
|
+
ids = [d['id'] for d in docs.get('rows', [])]
|
|
190
|
+
self.db.bulkDeleteByIDs(ids)
|
|
191
|
+
return ids
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""LogDB Exceptions"""
|
|
2
|
+
|
|
3
|
+
class LogDBError(Exception):
|
|
4
|
+
"""Standard error baseclass"""
|
|
5
|
+
def __init__(self, error):
|
|
6
|
+
Exception.__init__(self, error)
|
|
7
|
+
self.msg = LogDBError.__class__.__name__
|
|
8
|
+
self.error = error
|
|
9
|
+
|
|
10
|
+
def __str__(self):
|
|
11
|
+
return "%s: %s" % (self.msg, self.error)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#-*- coding: utf-8 -*-
|
|
3
|
+
#pylint: disable=
|
|
4
|
+
"""
|
|
5
|
+
File : LogDBReport.py
|
|
6
|
+
Author : Valentin Kuznetsov <vkuznet AT gmail dot com>
|
|
7
|
+
Description: LogDB report class to represent LogDB messages
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import print_function
|
|
10
|
+
|
|
11
|
+
from builtins import range
|
|
12
|
+
from builtins import object
|
|
13
|
+
|
|
14
|
+
class LogDBReport(object):
|
|
15
|
+
"""LogDBReport class to represent LogDB messages"""
|
|
16
|
+
def __init__(self, logdb):
|
|
17
|
+
self.logdb = logdb
|
|
18
|
+
|
|
19
|
+
def docs(self, request):
|
|
20
|
+
"""Fetch LogDB messages for given request"""
|
|
21
|
+
if request == 'all':
|
|
22
|
+
docs = self.logdb.get_all_requests()
|
|
23
|
+
else:
|
|
24
|
+
docs = self.logdb.get(request)
|
|
25
|
+
return docs
|
|
26
|
+
|
|
27
|
+
def orderby(self, docs, order):
|
|
28
|
+
"""Order LogDB messages by given type"""
|
|
29
|
+
odict = {}
|
|
30
|
+
for item in docs:
|
|
31
|
+
odict[item['ts']] = item
|
|
32
|
+
keys = sorted(odict.keys())
|
|
33
|
+
keys.reverse()
|
|
34
|
+
out = []
|
|
35
|
+
for key in keys:
|
|
36
|
+
out.append(odict[key])
|
|
37
|
+
return out
|
|
38
|
+
|
|
39
|
+
def to_json(self, request, order='ts'):
|
|
40
|
+
"""Represent given messages in JSON data-format for given set of requests"""
|
|
41
|
+
docs = self.orderby(self.docs(request), order)
|
|
42
|
+
return docs
|
|
43
|
+
|
|
44
|
+
def to_txt(self, request, order='ts', sep=' '):
|
|
45
|
+
"""Represent given messages in ASCII text format for given set of requests"""
|
|
46
|
+
docs = self.orderby(self.docs(request), order)
|
|
47
|
+
keys = list(docs[0])
|
|
48
|
+
out = sep.join(keys) + '\n'
|
|
49
|
+
for doc in docs:
|
|
50
|
+
values = []
|
|
51
|
+
for key in keys:
|
|
52
|
+
values.append('%s' % doc[key])
|
|
53
|
+
out += sep.join(values) + '\n'
|
|
54
|
+
return out
|
|
55
|
+
|
|
56
|
+
def to_html(self, request, order='ts'):
|
|
57
|
+
"""Represent given messages in ASCII text format for given set of requests"""
|
|
58
|
+
out = '<table id="logdb-report">\n'
|
|
59
|
+
for doc in self.to_txt(request, order, sep='</td><td>').split('\n'):
|
|
60
|
+
if doc:
|
|
61
|
+
out += '<tr><td>'+doc+'</td></tr>\n'
|
|
62
|
+
out += '</table>'
|
|
63
|
+
return out
|
|
64
|
+
|
|
65
|
+
def to_stdout(self, request, order='ts'):
|
|
66
|
+
"""Yield to stdout LogDB messages for given request/type"""
|
|
67
|
+
msg = '\nReport for %s' % request
|
|
68
|
+
print(msg, '\n', '-'*len(msg))
|
|
69
|
+
docs = self.orderby(self.docs(request), order)
|
|
70
|
+
times = []
|
|
71
|
+
messages = []
|
|
72
|
+
mtypes = []
|
|
73
|
+
for doc in docs:
|
|
74
|
+
times.append(str(doc['ts']))
|
|
75
|
+
messages.append(doc['msg'])
|
|
76
|
+
mtypes.append(doc['type'])
|
|
77
|
+
tstpad = max([len(t) for t in times])
|
|
78
|
+
msgpad = max([len(m) for m in messages])
|
|
79
|
+
mtppad = max([len(m) for m in mtypes])
|
|
80
|
+
out = []
|
|
81
|
+
for idx in range(len(times)):
|
|
82
|
+
tcol = '%s%s' % (times[idx], ' '*(tstpad-len(times[idx])))
|
|
83
|
+
mcol = '%s%s' % (messages[idx], ' '*(msgpad-len(messages[idx])))
|
|
84
|
+
ecol = '%s%s' % (mtypes[idx], ' '*(mtppad-len(mtypes[idx])))
|
|
85
|
+
print("%s %s %s" % (tcol, mcol, ecol))
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module contains a few basic WMCore-related utilitarian functions
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from Utils.CertTools import ckey, cert
|
|
6
|
+
|
|
7
|
+
from WMCore.Services.pycurl_manager import RequestHandler
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def makeHttpRequest(srvUrl, payload=None, method='GET', headers=None, encode=True, decode=True, payloadSizeToDump=50):
|
|
11
|
+
"""
|
|
12
|
+
Perform HTTP call to provided service URL. This can be any of supported methods like
|
|
13
|
+
GET, POST, PUT, DELETE. It will return HTTP response from upstream MicroService
|
|
14
|
+
and parse it accordingly (the WMCore MS service returns results as {'result': {'data':...}}
|
|
15
|
+
HTTP response.
|
|
16
|
+
|
|
17
|
+
:param srvUrl: string with the service url
|
|
18
|
+
:param payload: payload query or document, in case of GET HTTP request it is query dictionary,
|
|
19
|
+
in case of POST/PUT HTTP requests it is JSON payload to the service
|
|
20
|
+
:param method: string, defines which HTTP method to use
|
|
21
|
+
:param headers: HTTP headers (presented as dictionarY)
|
|
22
|
+
:param encode: boolean to reflect if data should be encoded, see pycurl_manager.py
|
|
23
|
+
:param decode: boolean to reflect if data should be decoded, see pycurl_manager.py
|
|
24
|
+
:param payloadSizeToDump: amount of characters to dump in a log from payload (to make log entries readable)
|
|
25
|
+
:return: returns a list with all objects, or raises
|
|
26
|
+
an exception in case of failure
|
|
27
|
+
"""
|
|
28
|
+
payload = payload or {}
|
|
29
|
+
mgr = RequestHandler()
|
|
30
|
+
headers = headers or {'Content-Type': 'application/json'}
|
|
31
|
+
data = mgr.getdata(srvUrl, payload, headers, verb=method,
|
|
32
|
+
ckey=ckey(), cert=cert(), encode=encode, decode=decode)
|
|
33
|
+
if data and data.get("result", []):
|
|
34
|
+
if "error" in data["result"][0]:
|
|
35
|
+
# strip off part of payload to make readable log message
|
|
36
|
+
sdata = f"{payload}"
|
|
37
|
+
if len(sdata) > payloadSizeToDump:
|
|
38
|
+
sdata = sdata[:payloadSizeToDump] + "..."
|
|
39
|
+
msg = f"Failed to contact {srvUrl} via {method} request with {sdata}"
|
|
40
|
+
msg += f" and error message: {data}"
|
|
41
|
+
raise RuntimeError(msg)
|
|
42
|
+
return data["result"]
|
|
43
|
+
|
|
44
|
+
def getPileupDocs(mspileupUrl, queryDict=None, method='GET'):
|
|
45
|
+
"""
|
|
46
|
+
Fetch documents from MSPileup according to the query passed in using POST.
|
|
47
|
+
|
|
48
|
+
:param mspileupUrl: string with the MSPileup url
|
|
49
|
+
:param queryDict: dictionary with the MongoDB query to run
|
|
50
|
+
:param method: string, defines which HTTP method to use
|
|
51
|
+
:return: returns a list with all the pileup objects, or raises
|
|
52
|
+
an exception in case of failure
|
|
53
|
+
"""
|
|
54
|
+
return makeHttpRequest(mspileupUrl, payload=queryDict, method=method)
|
|
File without changes
|