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
Utils/Throttled.py
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# pylint: disable-msg=C0103,C0111,W0212
|
|
2
|
+
"""
|
|
3
|
+
Throttled module defines necessary classes to throttle context.
|
|
4
|
+
Should be used in Web server APIs which wants to throttle clients.
|
|
5
|
+
|
|
6
|
+
The counter based approach, implemented in _ThrottleCounter class,
|
|
7
|
+
defines throttling on total number of user access to the underlying
|
|
8
|
+
app. But its counter depends on time execution of the API.
|
|
9
|
+
|
|
10
|
+
The time based approach, implemented in _ThrottleTimeCount class,
|
|
11
|
+
count total number of user accesses within specified time interval
|
|
12
|
+
regardless of time execution of the underlying API(s).
|
|
13
|
+
|
|
14
|
+
Here is an example how to use this module/classes:
|
|
15
|
+
|
|
16
|
+
# counter based throttline
|
|
17
|
+
|
|
18
|
+
from Utils.Throttling import UserThrottle
|
|
19
|
+
thr = UserThrottle(limit=5) # adjust threshold limit here
|
|
20
|
+
@thr.make_throttled()
|
|
21
|
+
def api():
|
|
22
|
+
# define your api logic here
|
|
23
|
+
|
|
24
|
+
# time based throttling
|
|
25
|
+
|
|
26
|
+
from Utils.Throttling import UserThrottleTime
|
|
27
|
+
thr = UserThrottleTime(limit=5) # adjust threshold limit here
|
|
28
|
+
@thr.make_throttled(trange=2) # adjust trange (in sec) here
|
|
29
|
+
def api():
|
|
30
|
+
# define your api logic here
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# standard modules
|
|
36
|
+
import time
|
|
37
|
+
from builtins import object
|
|
38
|
+
import logging
|
|
39
|
+
import threading
|
|
40
|
+
|
|
41
|
+
# cherrypy modules
|
|
42
|
+
import cherrypy
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class _ThrottleCounter(object):
|
|
46
|
+
"""
|
|
47
|
+
_ThrottleCounter class defines throttle parameter and
|
|
48
|
+
enter/exit methods to work with `with` context.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, throttle, user, debug=False):
|
|
52
|
+
self.throttle = throttle
|
|
53
|
+
self.user = user
|
|
54
|
+
if debug:
|
|
55
|
+
self.throttle.logger.setLevel(logging.DEBUG)
|
|
56
|
+
|
|
57
|
+
def __enter__(self):
|
|
58
|
+
"Define enter method for `with` context"
|
|
59
|
+
ctr = self.throttle._incUser(self.user)
|
|
60
|
+
msg = "Entering throttled function with counter %d for user %s" \
|
|
61
|
+
% (ctr, self.user)
|
|
62
|
+
self.throttle.logger.debug(msg)
|
|
63
|
+
if ctr > self.throttle.getLimit():
|
|
64
|
+
msg = "The current number of active operations for this resource"
|
|
65
|
+
msg += " exceeds the limit of %d for user %s" \
|
|
66
|
+
% (self.throttle.getLimit(), self.user)
|
|
67
|
+
raise cherrypy.HTTPError("429 Too Many Requests", msg)
|
|
68
|
+
|
|
69
|
+
def __exit__(self, exc_type, exc_value, exc_traceback):
|
|
70
|
+
"Define exit method for `with` context"
|
|
71
|
+
ctr = self.throttle._decUser(self.user)
|
|
72
|
+
msg = "Exiting throttled function with counter %d for user %s" \
|
|
73
|
+
% (ctr, self.user)
|
|
74
|
+
self.throttle.logger.debug(msg)
|
|
75
|
+
|
|
76
|
+
class _ThrottleTimeCounter(object):
|
|
77
|
+
"""
|
|
78
|
+
_ThrottleTimeCounter class defines time range throttled mechanism
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, throttle, user, trange):
|
|
82
|
+
self.throttle = throttle
|
|
83
|
+
self.user = user
|
|
84
|
+
self.trange = trange
|
|
85
|
+
|
|
86
|
+
def __enter__(self):
|
|
87
|
+
"Define enter method for `with` context"
|
|
88
|
+
ctr = self.throttle._incUser(self.user, self.trange)
|
|
89
|
+
if ctr > self.throttle.getLimit():
|
|
90
|
+
self.throttle._decUser(self.user)
|
|
91
|
+
msg = "The current number of active operations for this resource"
|
|
92
|
+
msg += " exceeds the limit of %d for user %s in last %s sec" \
|
|
93
|
+
% (self.throttle.getLimit(), self.user, self.trange)
|
|
94
|
+
raise cherrypy.HTTPError("429 Too Many Requests", msg)
|
|
95
|
+
|
|
96
|
+
def __exit__(self, exc_type, exc_value, exc_traceback):
|
|
97
|
+
"Define exit method for `with` context"
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class UserThrottleTime(object):
|
|
102
|
+
"""
|
|
103
|
+
UserThrottle class defines how to handle throttle time range based mechanism.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
def __init__(self, limit=3):
|
|
107
|
+
self.lock = threading.Lock()
|
|
108
|
+
self.users = {}
|
|
109
|
+
self.users_time = {}
|
|
110
|
+
self.limit = limit
|
|
111
|
+
|
|
112
|
+
def getLimit(self):
|
|
113
|
+
"Return throttle limit"
|
|
114
|
+
return self.limit
|
|
115
|
+
|
|
116
|
+
def throttleContext(self, user, trange=60):
|
|
117
|
+
"""
|
|
118
|
+
Define throttle context via _ThrottleTimeCounter class
|
|
119
|
+
which will count number of requests given user made in trange
|
|
120
|
+
:param user: user name
|
|
121
|
+
:param trange: time range while keep user access history
|
|
122
|
+
"""
|
|
123
|
+
return _ThrottleTimeCounter(self, user, trange)
|
|
124
|
+
|
|
125
|
+
def make_throttled(self, trange=60):
|
|
126
|
+
"decorator for throttled context"
|
|
127
|
+
def throttled_decorator(fn):
|
|
128
|
+
def throttled_wrapped_function(*args, **kw):
|
|
129
|
+
username = cherrypy.request.user.get('login', 'Unknown') \
|
|
130
|
+
if hasattr(cherrypy.request, 'user') else 'Unknown'
|
|
131
|
+
with self.throttleContext(username, trange):
|
|
132
|
+
return fn(*args, **kw)
|
|
133
|
+
return throttled_wrapped_function
|
|
134
|
+
return throttled_decorator
|
|
135
|
+
|
|
136
|
+
def reset(self, user):
|
|
137
|
+
"Reset user activities, i.e. access counter and last time of access"
|
|
138
|
+
self.users[user] = 0
|
|
139
|
+
self.users_time[user] = time.time()
|
|
140
|
+
|
|
141
|
+
def _incUser(self, user, trange=60):
|
|
142
|
+
"increment user count"
|
|
143
|
+
with self.lock:
|
|
144
|
+
self.users.setdefault(user, 0)
|
|
145
|
+
last_time = self.users_time.setdefault(user, time.time())
|
|
146
|
+
# increase counter within our trange
|
|
147
|
+
if abs(time.time()-last_time) < trange:
|
|
148
|
+
self.users[user] += 1
|
|
149
|
+
else:
|
|
150
|
+
self.reset(user)
|
|
151
|
+
return self.users[user]
|
|
152
|
+
|
|
153
|
+
def _decUser(self, user, trange=60):
|
|
154
|
+
"decrecrement user count"
|
|
155
|
+
with self.lock:
|
|
156
|
+
# decrease counter outside of our trange
|
|
157
|
+
last_time = self.users_time[user]
|
|
158
|
+
if abs(time.time()-last_time) < trange:
|
|
159
|
+
# gradually decrease user counter based on his/her elapsed time
|
|
160
|
+
step = int(trange - abs(time.time()-last_time))
|
|
161
|
+
self.users[user] -= step
|
|
162
|
+
if self.users[user] < 0:
|
|
163
|
+
self.reset(user)
|
|
164
|
+
else:
|
|
165
|
+
self.reset(user)
|
|
166
|
+
|
|
167
|
+
class UserThrottle(object):
|
|
168
|
+
"""
|
|
169
|
+
UserThrottle class defines throttle counter based mechanism.
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
def __init__(self, limit=3):
|
|
173
|
+
self.lock = threading.Lock()
|
|
174
|
+
self.tls = threading.local()
|
|
175
|
+
self.users = {}
|
|
176
|
+
self.limit = limit
|
|
177
|
+
self.logger = logging.getLogger("WMCore.UserThrottle")
|
|
178
|
+
|
|
179
|
+
def getLimit(self):
|
|
180
|
+
"Return throttle limit"
|
|
181
|
+
return self.limit
|
|
182
|
+
|
|
183
|
+
def throttleContext(self, user, debug=False):
|
|
184
|
+
"defint throttle context"
|
|
185
|
+
self.users.setdefault(user, 0)
|
|
186
|
+
return _ThrottleCounter(self, user, debug)
|
|
187
|
+
|
|
188
|
+
def make_throttled(self, debug=False):
|
|
189
|
+
"""
|
|
190
|
+
decorator for throttled context
|
|
191
|
+
"""
|
|
192
|
+
def throttled_decorator(fn):
|
|
193
|
+
"""
|
|
194
|
+
A decorator
|
|
195
|
+
"""
|
|
196
|
+
def throttled_wrapped_function(*args, **kw):
|
|
197
|
+
"""
|
|
198
|
+
A wrapped function.
|
|
199
|
+
"""
|
|
200
|
+
username = cherrypy.request.user.get('login', 'Unknown') \
|
|
201
|
+
if hasattr(cherrypy.request, 'user') else 'Unknown'
|
|
202
|
+
with self.throttleContext(username, debug):
|
|
203
|
+
return fn(*args, **kw)
|
|
204
|
+
return throttled_wrapped_function
|
|
205
|
+
return throttled_decorator
|
|
206
|
+
|
|
207
|
+
def _incUser(self, user):
|
|
208
|
+
"increment user count"
|
|
209
|
+
retval = 0
|
|
210
|
+
with self.lock:
|
|
211
|
+
retval = self.users[user]
|
|
212
|
+
if getattr(self.tls, 'count', None) is None:
|
|
213
|
+
self.tls.count = 0
|
|
214
|
+
self.tls.count += 1
|
|
215
|
+
if self.tls.count == 1:
|
|
216
|
+
self.users[user] = retval + 1
|
|
217
|
+
return retval
|
|
218
|
+
|
|
219
|
+
def _decUser(self, user):
|
|
220
|
+
"decrecrement user count"
|
|
221
|
+
retval = 0
|
|
222
|
+
with self.lock:
|
|
223
|
+
retval = self.users[user]
|
|
224
|
+
self.tls.count -= 1
|
|
225
|
+
if self.tls.count == 0:
|
|
226
|
+
self.users[user] = retval - 1
|
|
227
|
+
return retval
|
Utils/Timers.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Utilities related to timing and performance testing
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from builtins import object
|
|
7
|
+
import logging
|
|
8
|
+
import time
|
|
9
|
+
import calendar
|
|
10
|
+
from datetime import tzinfo, timedelta
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def gmtimeSeconds():
|
|
14
|
+
"""
|
|
15
|
+
Return GMT time in seconds
|
|
16
|
+
"""
|
|
17
|
+
return int(time.mktime(time.gmtime()))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def encodeTimestamp(secs):
|
|
21
|
+
"""
|
|
22
|
+
Encode second since epoch to a string GMT timezone representation
|
|
23
|
+
:param secs: input timestamp value (either int or float) in seconds since epoch
|
|
24
|
+
|
|
25
|
+
:return: time string in GMT timezone representation
|
|
26
|
+
"""
|
|
27
|
+
if not isinstance(secs, (int, float)):
|
|
28
|
+
raise Exception("Wrong input, should be seconds since epoch either int or float value")
|
|
29
|
+
return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(int(secs)))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def decodeTimestamp(timeString):
|
|
33
|
+
"""
|
|
34
|
+
Decode timestamps in provided document
|
|
35
|
+
:param timeString: timestamp string represention in GMT timezone, see encodeTimestamp
|
|
36
|
+
|
|
37
|
+
:return: seconds since ecouch in GMT timezone
|
|
38
|
+
"""
|
|
39
|
+
if not isinstance(timeString, str):
|
|
40
|
+
raise Exception("Wrong input, should be time string in GMT timezone representation")
|
|
41
|
+
return calendar.timegm(time.strptime(timeString, "%Y-%m-%dT%H:%M:%SZ"))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def timeFunction(func):
|
|
45
|
+
"""
|
|
46
|
+
source: https://www.andreas-jung.com/contents/a-python-decorator-for-measuring-the-execution-time-of-methods
|
|
47
|
+
|
|
48
|
+
Decorator function to measure how long a method/function takes to run
|
|
49
|
+
It returns a tuple with:
|
|
50
|
+
* wall clock time spent
|
|
51
|
+
* returned result of the function
|
|
52
|
+
* the function name
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def wrapper(*arg, **kw):
|
|
56
|
+
t1 = time.time()
|
|
57
|
+
res = func(*arg, **kw)
|
|
58
|
+
t2 = time.time()
|
|
59
|
+
return round((t2 - t1), 4), res, func.__name__
|
|
60
|
+
|
|
61
|
+
return wrapper
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class CodeTimer(object):
|
|
65
|
+
"""
|
|
66
|
+
A context manager for timing function calls.
|
|
67
|
+
Adapted from https://www.blog.pythonlibrary.org/2016/05/24/python-101-an-intro-to-benchmarking-your-code/
|
|
68
|
+
|
|
69
|
+
Use like
|
|
70
|
+
|
|
71
|
+
with CodeTimer(label='Doing something'):
|
|
72
|
+
do_something()
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, label='The function', logger=None):
|
|
76
|
+
self.start = time.time()
|
|
77
|
+
self.label = label
|
|
78
|
+
self.logger = logger or logging.getLogger()
|
|
79
|
+
|
|
80
|
+
def __enter__(self):
|
|
81
|
+
return self
|
|
82
|
+
|
|
83
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
84
|
+
end = time.time()
|
|
85
|
+
runtime = round((end - self.start), 3)
|
|
86
|
+
self.logger.info(f"{self.label} took {runtime} seconds to complete")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class LocalTimezone(tzinfo):
|
|
90
|
+
"""
|
|
91
|
+
A required python 2 class to determine current timezone for formatting rfc3339 timestamps
|
|
92
|
+
Required for sending alerts to the MONIT AlertManager
|
|
93
|
+
Can be removed once WMCore starts using python3
|
|
94
|
+
|
|
95
|
+
Details of class can be found at: https://docs.python.org/2/library/datetime.html#tzinfo-objects
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def __init__(self):
|
|
99
|
+
super(LocalTimezone, self).__init__()
|
|
100
|
+
self.ZERO = timedelta(0)
|
|
101
|
+
self.STDOFFSET = timedelta(seconds=-time.timezone)
|
|
102
|
+
if time.daylight:
|
|
103
|
+
self.DSTOFFSET = timedelta(seconds=-time.altzone)
|
|
104
|
+
else:
|
|
105
|
+
self.DSTOFFSET = self.STDOFFSET
|
|
106
|
+
|
|
107
|
+
self.DSTDIFF = self.DSTOFFSET - self.STDOFFSET
|
|
108
|
+
|
|
109
|
+
def utcoffset(self, dt):
|
|
110
|
+
if self._isdst(dt):
|
|
111
|
+
return self.DSTOFFSET
|
|
112
|
+
else:
|
|
113
|
+
return self.STDOFFSET
|
|
114
|
+
|
|
115
|
+
def dst(self, dt):
|
|
116
|
+
if self._isdst(dt):
|
|
117
|
+
return self.DSTDIFF
|
|
118
|
+
else:
|
|
119
|
+
return self.ZERO
|
|
120
|
+
|
|
121
|
+
def tzname(self, dt):
|
|
122
|
+
return time.tzname[self._isdst(dt)]
|
|
123
|
+
|
|
124
|
+
def _isdst(self, dt):
|
|
125
|
+
tt = (dt.year, dt.month, dt.day,
|
|
126
|
+
dt.hour, dt.minute, dt.second,
|
|
127
|
+
dt.weekday(), 0, 0)
|
|
128
|
+
stamp = time.mktime(tt)
|
|
129
|
+
tt = time.localtime(stamp)
|
|
130
|
+
return tt.tm_isdst > 0
|
Utils/Timestamps.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
_Timestamps_ module designed to insert proper WM timing into WMCore FJR.
|
|
4
|
+
Usage: python3 Timestamps.py --reportFile=$outputFile --wmJobStart=<sec> --wmJobEnd=<sec>
|
|
5
|
+
where outputFile represents output FJR file, and wmJobStart/wmJobEnd represent
|
|
6
|
+
start and end time of WM job, respectively.
|
|
7
|
+
|
|
8
|
+
NOTE: this script should reside in Utils area of WMCore repository since it is required
|
|
9
|
+
at run time on condor node where there is no WMCore installation and we only provide WMCore.zip
|
|
10
|
+
archive, and worker node may not have unzip tool to extract this script.
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import getopt
|
|
15
|
+
import logging
|
|
16
|
+
import os
|
|
17
|
+
import pickle
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# script options
|
|
22
|
+
options = {"reportFile=": "", "wmJobStart=": '', "wmJobEnd=": ''}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def addTimestampMetrics(config, wmJobStart, wmJobEnd):
|
|
26
|
+
"""
|
|
27
|
+
Adjust timestamp metrics of provied FJR data.
|
|
28
|
+
|
|
29
|
+
:param config: input FJR data
|
|
30
|
+
:param wmJobStart: start time of WM job in seconds
|
|
31
|
+
:param wmJobEnd: end time of WM job in seconds
|
|
32
|
+
"""
|
|
33
|
+
wmTiming = config.section_('WMTiming')
|
|
34
|
+
wmTiming.WMJobStart = wmJobStart
|
|
35
|
+
wmTiming.WMJobEnd = wmJobEnd
|
|
36
|
+
wmTiming.WMTotalWallClockTime = wmJobEnd - wmJobStart
|
|
37
|
+
return config
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def main():
|
|
41
|
+
"""
|
|
42
|
+
Main function of the script performs business logic:
|
|
43
|
+
- parse input arguments
|
|
44
|
+
- read provided input FJR
|
|
45
|
+
- adjust timestamp metrics of FJR data
|
|
46
|
+
- write out FJR
|
|
47
|
+
"""
|
|
48
|
+
try:
|
|
49
|
+
opts, _ = getopt.getopt(sys.argv[1:], "", list(options.keys()))
|
|
50
|
+
except getopt.GetoptError as ex:
|
|
51
|
+
msg = "Error processing commandline args:\n"
|
|
52
|
+
msg += str(ex)
|
|
53
|
+
logging.error(msg)
|
|
54
|
+
sys.exit(1)
|
|
55
|
+
|
|
56
|
+
for opt, arg in opts:
|
|
57
|
+
if opt == "--reportFile":
|
|
58
|
+
reportFile = arg
|
|
59
|
+
if opt == "--wmJobStart":
|
|
60
|
+
wmJobStart = float(arg)
|
|
61
|
+
if opt == "--wmJobEnd":
|
|
62
|
+
wmJobEnd = float(arg)
|
|
63
|
+
|
|
64
|
+
# read content of given FJR report file
|
|
65
|
+
data = {}
|
|
66
|
+
with open(reportFile, 'rb') as istream:
|
|
67
|
+
data = pickle.load(istream)
|
|
68
|
+
|
|
69
|
+
# adjust FJR data with provided metrics
|
|
70
|
+
data = addTimestampMetrics(data, wmJobStart, wmJobEnd)
|
|
71
|
+
|
|
72
|
+
# write content of FJR back to report file
|
|
73
|
+
reportOutFile = reportFile + ".new"
|
|
74
|
+
msg = f"Adding wmJobTime metric to {reportFile}"
|
|
75
|
+
with open(reportOutFile, 'wb') as ostream:
|
|
76
|
+
logging.info(msg)
|
|
77
|
+
pickle.dump(data, ostream)
|
|
78
|
+
|
|
79
|
+
# if we successfully wrote reportOutFile we can swap it with input one
|
|
80
|
+
sizeStatus = os.path.getsize(reportOutFile) >= os.path.getsize(reportFile)
|
|
81
|
+
if os.path.isfile(reportOutFile) and sizeStatus:
|
|
82
|
+
os.rename(reportOutFile, reportFile)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == '__main__':
|
|
86
|
+
main()
|
Utils/TokenManager.py
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
#pylint: disable=W0212
|
|
4
|
+
"""
|
|
5
|
+
File : TokenManager.py
|
|
6
|
+
Author : Valentin Kuznetsov <vkuznet AT gmail dot com>
|
|
7
|
+
Description: IAM token manager
|
|
8
|
+
by default it relies on the following environment/parameters:
|
|
9
|
+
- IAM_TOKEN is either file name or actual token value
|
|
10
|
+
- https://cms-auth.web.cern.ch/jwk is default CMS IAM provider
|
|
11
|
+
- https://wlcg.cern.ch/jwt/v1/any is default for audience parameter
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
# system modules
|
|
15
|
+
import os
|
|
16
|
+
import ssl
|
|
17
|
+
import time
|
|
18
|
+
import logging
|
|
19
|
+
import traceback
|
|
20
|
+
|
|
21
|
+
# third part library
|
|
22
|
+
try:
|
|
23
|
+
import jwt
|
|
24
|
+
except ImportError:
|
|
25
|
+
traceback.print_exc()
|
|
26
|
+
jwt = None
|
|
27
|
+
|
|
28
|
+
from Utils.Utilities import encodeUnicodeToBytes
|
|
29
|
+
|
|
30
|
+
# prevent "SSL: CERTIFICATE_VERIFY_FAILED" error
|
|
31
|
+
# this will cause pylint warning W0212, therefore we ignore it above
|
|
32
|
+
ssl._create_default_https_context = ssl._create_unverified_context
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def readToken(name=None):
|
|
36
|
+
"""
|
|
37
|
+
Read IAM token either from environment or file name
|
|
38
|
+
:param name: ether file name containing token or environment name which hold the token value.
|
|
39
|
+
If not provided it will be assumed to read token from IAM_TOKEN environment.
|
|
40
|
+
:return: token or None
|
|
41
|
+
"""
|
|
42
|
+
if name and os.path.exists(name):
|
|
43
|
+
token = None
|
|
44
|
+
with open(name, 'r', encoding='utf-8') as istream:
|
|
45
|
+
token = istream.read()
|
|
46
|
+
return token
|
|
47
|
+
if name:
|
|
48
|
+
return os.environ.get(name)
|
|
49
|
+
return os.environ.get("IAM_TOKEN")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def tokenData(token, url="https://cms-auth.web.cern.ch/jwk", audUrl="https://wlcg.cern.ch/jwt/v1/any"):
|
|
53
|
+
"""
|
|
54
|
+
inspect and extract token data
|
|
55
|
+
:param token: token string
|
|
56
|
+
:param url: IAM provider URL
|
|
57
|
+
:param audUrl: audience string
|
|
58
|
+
"""
|
|
59
|
+
if not token or not jwt:
|
|
60
|
+
return {}
|
|
61
|
+
if isinstance(token, str):
|
|
62
|
+
token = encodeUnicodeToBytes(token)
|
|
63
|
+
jwksClient = jwt.PyJWKClient(url)
|
|
64
|
+
signingKey = jwksClient.get_signing_key_from_jwt(token)
|
|
65
|
+
key = signingKey.key
|
|
66
|
+
headers = jwt.get_unverified_header(token)
|
|
67
|
+
alg = headers.get('alg', 'RS256')
|
|
68
|
+
data = jwt.decode(
|
|
69
|
+
token,
|
|
70
|
+
key,
|
|
71
|
+
algorithms=[alg],
|
|
72
|
+
audience=audUrl,
|
|
73
|
+
options={"verify_exp": True},
|
|
74
|
+
)
|
|
75
|
+
return data
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def isValidToken(token):
|
|
79
|
+
"""
|
|
80
|
+
check if given token is valid or not
|
|
81
|
+
|
|
82
|
+
:param token: token string
|
|
83
|
+
:return: true or false
|
|
84
|
+
"""
|
|
85
|
+
tokenDict = {}
|
|
86
|
+
tokenDict = tokenData(token)
|
|
87
|
+
exp = tokenDict.get('exp', 0) # expire, seconds since epoch
|
|
88
|
+
if not exp or exp < time.time():
|
|
89
|
+
return False
|
|
90
|
+
return True
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class TokenManager():
|
|
94
|
+
"""
|
|
95
|
+
TokenManager class handles IAM tokens
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def __init__(self,
|
|
99
|
+
name=None,
|
|
100
|
+
url="https://cms-auth.web.cern.ch/jwk",
|
|
101
|
+
audUrl="https://wlcg.cern.ch/jwt/v1/any",
|
|
102
|
+
logger=None):
|
|
103
|
+
"""
|
|
104
|
+
Token manager reads IAM tokens either from file or env.
|
|
105
|
+
It caches token along with expiration timestamp.
|
|
106
|
+
By default the env variable to use is IAM_TOKEN.
|
|
107
|
+
:param name: string representing either file or env where we should read token from
|
|
108
|
+
:param url: IAM provider URL
|
|
109
|
+
:param audUrl: audience string
|
|
110
|
+
:param logger: logger object or none to use default one
|
|
111
|
+
"""
|
|
112
|
+
self.name = name
|
|
113
|
+
self.url = url
|
|
114
|
+
self.audUrl = audUrl
|
|
115
|
+
self.expire = 0
|
|
116
|
+
self.token = None
|
|
117
|
+
self.logger = logger if logger else logging.getLogger()
|
|
118
|
+
try:
|
|
119
|
+
self.token = self.getToken()
|
|
120
|
+
except Exception as exc:
|
|
121
|
+
self.logger.exception("Failed to get token. Details: %s", str(exc))
|
|
122
|
+
|
|
123
|
+
def getToken(self):
|
|
124
|
+
"""
|
|
125
|
+
Return valid token and sets its expire timestamp
|
|
126
|
+
"""
|
|
127
|
+
if not self.token or not isValidToken(self.token):
|
|
128
|
+
self.token = readToken(self.name)
|
|
129
|
+
tokenDict = {}
|
|
130
|
+
try:
|
|
131
|
+
tokenDict = tokenData(self.token, url=self.url, audUrl=self.audUrl)
|
|
132
|
+
self.logger.debug(tokenDict)
|
|
133
|
+
except Exception as exc:
|
|
134
|
+
self.logger.exception(str(exc))
|
|
135
|
+
raise
|
|
136
|
+
self.expire = tokenDict.get('exp', 0)
|
|
137
|
+
return self.token
|
|
138
|
+
|
|
139
|
+
def getLifetime(self):
|
|
140
|
+
"""
|
|
141
|
+
Return reamaining lifetime of existing token
|
|
142
|
+
"""
|
|
143
|
+
return self.expire - int(time.time())
|
Utils/Tracing.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Stuff to help with debugging from https://pymotw.com/3/sys/tracing.html
|
|
5
|
+
|
|
6
|
+
Use like this:
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
from Utils.Tracing import trace_calls_and_returns, dont_trace
|
|
10
|
+
|
|
11
|
+
sys.settrace(trace_calls_and_returns)
|
|
12
|
+
# Do the things you want to trace
|
|
13
|
+
sys.settrace(dont_trace)
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def trace_calls(frame, event, arg, to_be_traced=None):
|
|
19
|
+
if event != 'call':
|
|
20
|
+
return
|
|
21
|
+
co = frame.f_code
|
|
22
|
+
func_name = co.co_name
|
|
23
|
+
if func_name == 'write':
|
|
24
|
+
return # Ignore write() calls from printing
|
|
25
|
+
line_no = frame.f_lineno
|
|
26
|
+
filename = co.co_filename
|
|
27
|
+
print('* Call to {} on line {} of {}'.format(
|
|
28
|
+
func_name, line_no, filename))
|
|
29
|
+
if func_name in to_be_traced:
|
|
30
|
+
# Trace into this function
|
|
31
|
+
return trace_lines
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def trace_calls_and_returns(frame, event, arg):
|
|
36
|
+
co = frame.f_code
|
|
37
|
+
func_name = co.co_name
|
|
38
|
+
if func_name == 'write':
|
|
39
|
+
return # Ignore write() calls from printing
|
|
40
|
+
line_no = frame.f_lineno
|
|
41
|
+
filename = co.co_filename
|
|
42
|
+
if event == 'call':
|
|
43
|
+
print('Call to {} on line {} of {}'.format(func_name, line_no, filename))
|
|
44
|
+
return trace_calls_and_returns
|
|
45
|
+
elif event == 'return':
|
|
46
|
+
print(' {} => {} ({})'.format(func_name, arg, filename))
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def trace_lines(frame, event, arg):
|
|
51
|
+
if event != 'line':
|
|
52
|
+
return
|
|
53
|
+
co = frame.f_code
|
|
54
|
+
func_name = co.co_name
|
|
55
|
+
line_no = frame.f_lineno
|
|
56
|
+
print('* {} line {}'.format(func_name, line_no))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def dont_trace(frame, event, arg):
|
|
60
|
+
return
|