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/IteratorTools.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
|
|
3
|
+
from builtins import str, map
|
|
4
|
+
import collections.abc
|
|
5
|
+
from itertools import islice, chain, groupby
|
|
6
|
+
|
|
7
|
+
def grouper(iterable, n):
|
|
8
|
+
"""
|
|
9
|
+
:param iterable: List of other iterable to slice
|
|
10
|
+
:type: iterable
|
|
11
|
+
:param n: Chunk size for resulting lists
|
|
12
|
+
:type: int
|
|
13
|
+
:return: iterator of the sliced list
|
|
14
|
+
|
|
15
|
+
Source: http://stackoverflow.com/questions/3992735/python-generator-that-groups-another-iterable-into-groups-of-n
|
|
16
|
+
"""
|
|
17
|
+
iterable = iter(iterable)
|
|
18
|
+
return iter(lambda: list(islice(iterable, n)), [])
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def getChunk(arr, step):
|
|
22
|
+
"""
|
|
23
|
+
Return chunk of entries from given array and step, it is similar in behavior to grouper
|
|
24
|
+
function but instead of returning new list it provides a generator iterable object.
|
|
25
|
+
:param arr: input array of data
|
|
26
|
+
:param step: step to iterate
|
|
27
|
+
:return: generator, set of slices with number of entries equal to step of iteration
|
|
28
|
+
"""
|
|
29
|
+
for i in range(0, len(arr), step):
|
|
30
|
+
yield arr[i:i + step]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def flattenList(doubleList):
|
|
34
|
+
"""
|
|
35
|
+
Make flat a list of lists.
|
|
36
|
+
"""
|
|
37
|
+
return list(chain.from_iterable(doubleList))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def nestedDictUpdate(d, u):
|
|
41
|
+
"""
|
|
42
|
+
Code from Alex Matelli
|
|
43
|
+
http://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth
|
|
44
|
+
"""
|
|
45
|
+
for k, v in u.items():
|
|
46
|
+
if isinstance(v, collections.abc.Mapping):
|
|
47
|
+
r = nestedDictUpdate(d.get(k, {}), v)
|
|
48
|
+
d[k] = r
|
|
49
|
+
else:
|
|
50
|
+
d[k] = u[k]
|
|
51
|
+
return d
|
|
52
|
+
|
|
53
|
+
def convertFromUnicodeToBytes(data):
|
|
54
|
+
"""
|
|
55
|
+
code fram
|
|
56
|
+
http://stackoverflow.com/questions/1254454/fastest-way-to-convert-a-dicts-keys-values-from-unicode-to-str
|
|
57
|
+
"""
|
|
58
|
+
if isinstance(data, str):
|
|
59
|
+
return data.encode('utf-8')
|
|
60
|
+
elif isinstance(data, collections.abc.Mapping):
|
|
61
|
+
return dict(list(map(convertFromUnicodeToBytes, list(data.items()))))
|
|
62
|
+
elif isinstance(data, collections.abc.Iterable):
|
|
63
|
+
return type(data)(list(map(convertFromUnicodeToBytes, data)))
|
|
64
|
+
else:
|
|
65
|
+
return data
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def makeListElementsUnique(listObj):
|
|
69
|
+
"""
|
|
70
|
+
Given a list of lists or a list of tuples, find all duplicate elements
|
|
71
|
+
and make them unique.
|
|
72
|
+
:param listObj: an unsorted list of lists or a list of tuples, e.g.:
|
|
73
|
+
[[1, 1], [1, 5], [1, 1]]; or
|
|
74
|
+
[(1, 1), (1, 5), (1, 1)]
|
|
75
|
+
:return: the same list object but with no duplicates
|
|
76
|
+
|
|
77
|
+
Source: https://stackoverflow.com/questions/2213923/removing-duplicates-from-a-list-of-lists
|
|
78
|
+
"""
|
|
79
|
+
listObj.sort()
|
|
80
|
+
return list(k for k, _ in groupby(listObj))
|
Utils/MathUtils.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Module containing mathematical and physics utils
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from builtins import int, str
|
|
8
|
+
from math import ceil
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def quantize(inputVal, quanta):
|
|
12
|
+
"""
|
|
13
|
+
_quantize_
|
|
14
|
+
|
|
15
|
+
Quantize the input value following the quanta provided.
|
|
16
|
+
"""
|
|
17
|
+
if isinstance(inputVal, str):
|
|
18
|
+
inputVal = float(inputVal)
|
|
19
|
+
elif not isinstance(inputVal, (int, float)):
|
|
20
|
+
msg = "Input value has to be either int or float, not %s" % (type(inputVal))
|
|
21
|
+
raise ValueError(msg)
|
|
22
|
+
|
|
23
|
+
if isinstance(quanta, (str, int, float)):
|
|
24
|
+
quanta = int(float(quanta))
|
|
25
|
+
elif not isinstance(quanta, int):
|
|
26
|
+
msg = "Quanta value has to be either int or float, not %s" % (type(quanta))
|
|
27
|
+
raise ValueError(msg)
|
|
28
|
+
|
|
29
|
+
res = int(ceil(inputVal / quanta))
|
|
30
|
+
|
|
31
|
+
return res * quanta
|
Utils/MemoryCache.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Simple in-memory and non-thread safe cache.
|
|
5
|
+
Note that this module does not support home-made object types, since there is
|
|
6
|
+
an explicit data type check when adding a new item to the cache.
|
|
7
|
+
|
|
8
|
+
It raises a TypeError exception if the cache data type chagens;
|
|
9
|
+
or if the user tries to extend the cache with an incompatible
|
|
10
|
+
data type.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from copy import copy
|
|
14
|
+
|
|
15
|
+
from builtins import object
|
|
16
|
+
from time import time
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MemoryCacheException(Exception):
|
|
20
|
+
def __init__(self, message):
|
|
21
|
+
super(MemoryCacheException, self).__init__(message)
|
|
22
|
+
|
|
23
|
+
class MemoryCache():
|
|
24
|
+
|
|
25
|
+
__slots__ = ["lastUpdate", "expiration", "_cache"]
|
|
26
|
+
|
|
27
|
+
def __init__(self, expiration, initialData=None):
|
|
28
|
+
"""
|
|
29
|
+
Initializes cache object
|
|
30
|
+
|
|
31
|
+
:param expiration: expiration time in seconds
|
|
32
|
+
:param initialData: initial value for the cache
|
|
33
|
+
"""
|
|
34
|
+
self.lastUpdate = int(time())
|
|
35
|
+
self.expiration = expiration
|
|
36
|
+
self._cache = initialData
|
|
37
|
+
|
|
38
|
+
def __contains__(self, item):
|
|
39
|
+
"""
|
|
40
|
+
Check whether item is in the current cache
|
|
41
|
+
:param item: a simple object (string, integer, etc)
|
|
42
|
+
:return: True if the object can be found in the cache, False otherwise
|
|
43
|
+
"""
|
|
44
|
+
return item in self._cache
|
|
45
|
+
|
|
46
|
+
def __getitem__(self, keyName):
|
|
47
|
+
"""
|
|
48
|
+
If the cache is a dictionary, return that item from the cache. Else, raise an exception.
|
|
49
|
+
:param keyName: the key name from the dictionary
|
|
50
|
+
"""
|
|
51
|
+
if isinstance(self._cache, dict):
|
|
52
|
+
return copy(self._cache.get(keyName))
|
|
53
|
+
else:
|
|
54
|
+
raise MemoryCacheException("Cannot retrieve an item from a non-dict MemoryCache object: {}".format(self._cache))
|
|
55
|
+
|
|
56
|
+
def reset(self):
|
|
57
|
+
"""
|
|
58
|
+
Resets the cache to its current data type
|
|
59
|
+
"""
|
|
60
|
+
if isinstance(self._cache, (dict, set)):
|
|
61
|
+
self._cache.clear()
|
|
62
|
+
elif isinstance(self._cache, list):
|
|
63
|
+
del self._cache[:]
|
|
64
|
+
else:
|
|
65
|
+
raise MemoryCacheException("The cache needs to be reset manually, data type unknown")
|
|
66
|
+
|
|
67
|
+
def isCacheExpired(self):
|
|
68
|
+
"""
|
|
69
|
+
Evaluate whether the cache has already expired, returning
|
|
70
|
+
True if it did, otherwise it returns False
|
|
71
|
+
"""
|
|
72
|
+
return self.lastUpdate + self.expiration < int(time())
|
|
73
|
+
|
|
74
|
+
def getCache(self):
|
|
75
|
+
"""
|
|
76
|
+
Raises an exception if the cache has expired, otherwise returns
|
|
77
|
+
its data
|
|
78
|
+
"""
|
|
79
|
+
if self.isCacheExpired():
|
|
80
|
+
expiredSince = int(time()) - (self.lastUpdate + self.expiration)
|
|
81
|
+
raise MemoryCacheException("Memory cache expired for %d seconds" % expiredSince)
|
|
82
|
+
return self._cache
|
|
83
|
+
|
|
84
|
+
def setCache(self, inputData):
|
|
85
|
+
"""
|
|
86
|
+
Refresh the cache with the content provided (refresh its expiration as well)
|
|
87
|
+
This method enforces the user to not change the cache data type
|
|
88
|
+
:param inputData: data to store in the cache
|
|
89
|
+
"""
|
|
90
|
+
if not isinstance(self._cache, type(inputData)):
|
|
91
|
+
raise TypeError("Current cache data type: %s, while new value is: %s" %
|
|
92
|
+
(type(self._cache), type(inputData)))
|
|
93
|
+
self.reset()
|
|
94
|
+
self.lastUpdate = int(time())
|
|
95
|
+
self._cache = inputData
|
|
96
|
+
|
|
97
|
+
def addItemToCache(self, inputItem):
|
|
98
|
+
"""
|
|
99
|
+
Adds new item(s) to the cache, without resetting its expiration.
|
|
100
|
+
It, of course, only works for data caches of type: list, set or dict.
|
|
101
|
+
:param inputItem: additional item to be added to the current cached data
|
|
102
|
+
"""
|
|
103
|
+
if isinstance(self._cache, set) and isinstance(inputItem, (list, set)):
|
|
104
|
+
# extend another list or set into a set
|
|
105
|
+
self._cache.update(inputItem)
|
|
106
|
+
elif isinstance(self._cache, set) and isinstance(inputItem, (int, float, str)):
|
|
107
|
+
# add a simple object (integer, string, etc) to a set
|
|
108
|
+
self._cache.add(inputItem)
|
|
109
|
+
elif isinstance(self._cache, list) and isinstance(inputItem, (list, set)):
|
|
110
|
+
# extend another list or set into a list
|
|
111
|
+
self._cache.extend(inputItem)
|
|
112
|
+
elif isinstance(self._cache, list) and isinstance(inputItem, (int, float, str)):
|
|
113
|
+
# add a simple object (integer, string, etc) to a list
|
|
114
|
+
self._cache.append(inputItem)
|
|
115
|
+
elif isinstance(self._cache, dict) and isinstance(inputItem, dict):
|
|
116
|
+
self._cache.update(inputItem)
|
|
117
|
+
else:
|
|
118
|
+
msg = "Input item type: %s cannot be added to a cache type: %s" % (type(self._cache), type(inputItem))
|
|
119
|
+
raise TypeError("Cache and input item data type mismatch. %s" % msg)
|
Utils/Patterns.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Patterns module provides set of CS patterns
|
|
3
|
+
"""
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
class Singleton(type):
|
|
7
|
+
"""Implementation of Singleton class"""
|
|
8
|
+
_instances = {}
|
|
9
|
+
def __call__(cls, *args, **kwargs):
|
|
10
|
+
if cls not in cls._instances:
|
|
11
|
+
cls._instances[cls] = \
|
|
12
|
+
super(Singleton, cls).__call__(*args, **kwargs)
|
|
13
|
+
return cls._instances[cls]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def getDomainName(urlStr):
|
|
17
|
+
"""
|
|
18
|
+
Given a URL string, return the domain name.
|
|
19
|
+
:param urlStr: URL string
|
|
20
|
+
:return: a string with the domain name (e.g. "cmsweb-prod")
|
|
21
|
+
"""
|
|
22
|
+
domainPattern = re.compile(r'https?://([^/]+)\.cern\.ch')
|
|
23
|
+
match = domainPattern.search(urlStr)
|
|
24
|
+
return match.group(1) if match else ""
|
Utils/Pipeline.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""
|
|
2
|
+
File : Pipeline.py
|
|
3
|
+
Description: Provides 2 basic classes:
|
|
4
|
+
- Functor: A class to create function calls from a function object
|
|
5
|
+
and arbitrary number of arguments
|
|
6
|
+
- Pipeline: A class to provide building blocks for creating functional
|
|
7
|
+
pipelines for cumulative execution on an arbitrary object
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from builtins import object
|
|
11
|
+
from functools import reduce
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Functor(object):
|
|
15
|
+
"""
|
|
16
|
+
A simple functor class used to construct a function call which later to be
|
|
17
|
+
applied on an (any type) object.
|
|
18
|
+
NOTE:
|
|
19
|
+
It expects a function in the constructor and an (any type) object
|
|
20
|
+
passed to the run or __call__ methods, which methods once called they
|
|
21
|
+
construct and return the following function:
|
|
22
|
+
func(obj, *args, **kwargs)
|
|
23
|
+
NOTE:
|
|
24
|
+
All the additional arguments which the function may take must be set in
|
|
25
|
+
the __init__ method. If any of them are passed during run time an error
|
|
26
|
+
will be raised.
|
|
27
|
+
|
|
28
|
+
:func:
|
|
29
|
+
The function to which the rest of the constructor arguments are about
|
|
30
|
+
to be attached and then the newly created function will be returned.
|
|
31
|
+
- The function needs to take at least one parameter since the object
|
|
32
|
+
passed to the run/__call__ methods will always be put as a first
|
|
33
|
+
argument to the function.
|
|
34
|
+
|
|
35
|
+
:Example:
|
|
36
|
+
|
|
37
|
+
def adder(a, b, *args, **kwargs):
|
|
38
|
+
if args:
|
|
39
|
+
print("adder args: %s" % args)
|
|
40
|
+
if kwargs:
|
|
41
|
+
print("adder kwargs: %s" % kwargs)
|
|
42
|
+
res = a + b
|
|
43
|
+
return res
|
|
44
|
+
|
|
45
|
+
>>> x=Functor(adder, 8, 'foo', bar=True)
|
|
46
|
+
>>> x(2)
|
|
47
|
+
adder args: foo
|
|
48
|
+
adder kwargs: {'bar': True}
|
|
49
|
+
adder res: 10
|
|
50
|
+
10
|
|
51
|
+
|
|
52
|
+
>>> x
|
|
53
|
+
<Pipeline.Functor instance at 0x7f319bbaeea8>
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
def __init__(self, func, *args, **kwargs):
|
|
58
|
+
"""
|
|
59
|
+
The init method for class Functor
|
|
60
|
+
"""
|
|
61
|
+
self.func = func
|
|
62
|
+
self.args = args
|
|
63
|
+
self.kwargs = kwargs
|
|
64
|
+
|
|
65
|
+
def __call__(self, obj):
|
|
66
|
+
"""
|
|
67
|
+
The call method for class Functor
|
|
68
|
+
"""
|
|
69
|
+
return self.run(obj)
|
|
70
|
+
|
|
71
|
+
def run(self, obj):
|
|
72
|
+
return self.func(obj, *self.args, **self.kwargs)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class Pipeline(object):
|
|
76
|
+
"""
|
|
77
|
+
A simple Functional Pipeline Class: applies a set of functions to an object,
|
|
78
|
+
where the output of every previous function is an input to the next one.
|
|
79
|
+
"""
|
|
80
|
+
# NOTE:
|
|
81
|
+
# Similar and inspiring approaches but yet some different implementations
|
|
82
|
+
# are discussed in the following two links [1] & [2]. With a quite good
|
|
83
|
+
# explanation in [1], which helped a lot. All in all at the bottom always
|
|
84
|
+
# sits the reduce function.
|
|
85
|
+
# [1]
|
|
86
|
+
# https://softwarejourneyman.com/python-function-pipelines.html
|
|
87
|
+
# [2]
|
|
88
|
+
# https://gitlab.com/mc706/functional-pipeline
|
|
89
|
+
|
|
90
|
+
def __init__(self, funcLine=None, name=None):
|
|
91
|
+
"""
|
|
92
|
+
:funcLine: A list of functions or Functors of function + arguments (see
|
|
93
|
+
the Class definition above) that are to be applied sequentially
|
|
94
|
+
to the object.
|
|
95
|
+
- If any of the elements of 'funcLine' is a function, a direct
|
|
96
|
+
function call with the object as an argument is performed.
|
|
97
|
+
- If any of the elements of 'funcLine' is a Functor, then the
|
|
98
|
+
first argument of the Functor constructor is the function to
|
|
99
|
+
be evaluated and the object is passed as a first argument to
|
|
100
|
+
the function with all the rest of the arguments passed right
|
|
101
|
+
after it eg. the following Functor in the funcLine:
|
|
102
|
+
|
|
103
|
+
Functor(func, 'foo', bar=True)
|
|
104
|
+
|
|
105
|
+
will result in the following function call later when the
|
|
106
|
+
pipeline is executed:
|
|
107
|
+
|
|
108
|
+
func(obj, 'foo', bar=True)
|
|
109
|
+
|
|
110
|
+
:Example:
|
|
111
|
+
(using the adder function from above and an object of type int)
|
|
112
|
+
|
|
113
|
+
>>> pipe = Pipeline([Functor(adder, 5),
|
|
114
|
+
Functor(adder, 6),
|
|
115
|
+
Functor(adder, 7, "extraArg"),
|
|
116
|
+
Functor(adder, 8, update=True)])
|
|
117
|
+
|
|
118
|
+
>>> pipe.run(1)
|
|
119
|
+
adder res: 6
|
|
120
|
+
adder res: 12
|
|
121
|
+
adder args: extraArg
|
|
122
|
+
adder res: 19
|
|
123
|
+
adder kwargs: {'update': True}
|
|
124
|
+
adder res: 27
|
|
125
|
+
"""
|
|
126
|
+
self.funcLine = funcLine or []
|
|
127
|
+
self.name = name
|
|
128
|
+
|
|
129
|
+
def getPipelineName(self):
|
|
130
|
+
"""
|
|
131
|
+
__getPipelineName__
|
|
132
|
+
"""
|
|
133
|
+
name = self.name or "Unnamed Pipeline"
|
|
134
|
+
return name
|
|
135
|
+
|
|
136
|
+
def run(self, obj):
|
|
137
|
+
return reduce(lambda obj, functor: functor(obj), self.funcLine, obj)
|
Utils/PortForward.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
_PortForward_
|
|
4
|
+
|
|
5
|
+
A decorator for swapping ports in an url
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from builtins import str, bytes
|
|
9
|
+
|
|
10
|
+
def portForward(port):
|
|
11
|
+
"""
|
|
12
|
+
Decorator wrapper function for port forwarding of the REST calls of any
|
|
13
|
+
function to a given port.
|
|
14
|
+
|
|
15
|
+
Currently there are three constraints for applying this decorator.
|
|
16
|
+
1. The function to be decorated must be defined within a class and not being a static method.
|
|
17
|
+
The reason for that is because we need to be sure the function's signature will
|
|
18
|
+
always include the class instance as its first argument.
|
|
19
|
+
2. The url argument must be present as the second one in the positional argument list
|
|
20
|
+
of the decorated function (right after the class instance argument).
|
|
21
|
+
3. The url must follow the syntax specifications in RFC 1808:
|
|
22
|
+
https://tools.ietf.org/html/rfc1808.html
|
|
23
|
+
|
|
24
|
+
If all of the above constraints are fulfilled and the url is part of the
|
|
25
|
+
urlMangleList, then the url is parsed and the port is substituted with the
|
|
26
|
+
one provided as an argument to the decorator's wrapper function.
|
|
27
|
+
|
|
28
|
+
param port: The port to which the REST call should be forwarded.
|
|
29
|
+
"""
|
|
30
|
+
def portForwardDecorator(callFunc):
|
|
31
|
+
"""
|
|
32
|
+
The actual decorator
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def portMangle(callObj, url, *args, **kwargs):
|
|
36
|
+
"""
|
|
37
|
+
Function used to check if the url coming with the current argument list
|
|
38
|
+
is to be forwarded and if so change the port to the one provided as an
|
|
39
|
+
argument to the decorator wrapper.
|
|
40
|
+
|
|
41
|
+
:param classObj: This is the class object (slef from within the class)
|
|
42
|
+
which is always to be present in the signature of a
|
|
43
|
+
public method. We will never use this argument, but
|
|
44
|
+
we need it there for not breaking the positional
|
|
45
|
+
argument order
|
|
46
|
+
:param url: This is the actual url to be (eventually) forwarded
|
|
47
|
+
:param *args: The positional argument list coming from the original function
|
|
48
|
+
:param *kwargs: The keywords argument list coming from the original function
|
|
49
|
+
"""
|
|
50
|
+
forwarded = False
|
|
51
|
+
try:
|
|
52
|
+
if isinstance(url, str):
|
|
53
|
+
urlToMangle = 'https://cmsweb'
|
|
54
|
+
if url.startswith(urlToMangle):
|
|
55
|
+
newUrl = url.replace('.cern.ch/', '.cern.ch:%d/' % port, 1)
|
|
56
|
+
forwarded = True
|
|
57
|
+
elif isinstance(url, bytes):
|
|
58
|
+
urlToMangle = b'https://cmsweb'
|
|
59
|
+
if url.startswith(urlToMangle):
|
|
60
|
+
newUrl = url.replace(b'.cern.ch/', b'.cern.ch:%d/' % port, 1)
|
|
61
|
+
forwarded = True
|
|
62
|
+
|
|
63
|
+
except Exception:
|
|
64
|
+
pass
|
|
65
|
+
if forwarded:
|
|
66
|
+
return callFunc(callObj, newUrl, *args, **kwargs)
|
|
67
|
+
else:
|
|
68
|
+
return callFunc(callObj, url, *args, **kwargs)
|
|
69
|
+
return portMangle
|
|
70
|
+
return portForwardDecorator
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class PortForward():
|
|
74
|
+
"""
|
|
75
|
+
A class with a call method implementing a simple way to use the functionality
|
|
76
|
+
provided by the protForward decorator as a pure functional call:
|
|
77
|
+
EXAMPLE:
|
|
78
|
+
from Utils.PortForward import PortForward
|
|
79
|
+
|
|
80
|
+
portForwarder = PortForward(8443)
|
|
81
|
+
url = 'https://cmsweb-testbed.cern.ch/couchdb'
|
|
82
|
+
url = portForwarder(url)
|
|
83
|
+
"""
|
|
84
|
+
def __init__(self, port):
|
|
85
|
+
"""
|
|
86
|
+
The init method for the PortForward call class. This one is supposed
|
|
87
|
+
to simply provide an initial class instance with a logger.
|
|
88
|
+
"""
|
|
89
|
+
self.port = port
|
|
90
|
+
|
|
91
|
+
def __call__(self, url):
|
|
92
|
+
"""
|
|
93
|
+
The call method for the PortForward class
|
|
94
|
+
"""
|
|
95
|
+
def dummyCall(self, url):
|
|
96
|
+
return url
|
|
97
|
+
return portForward(self.port)(dummyCall)(self, url)
|
Utils/ProcessStats.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
File : ProcessStats.py
|
|
5
|
+
Author : Valentin Kuznetsov <vkuznet AT gmail dot com>
|
|
6
|
+
Description: This module provide ability to get detailed information about
|
|
7
|
+
certain UNIX process, referred by PID. It is based on psutil and threading
|
|
8
|
+
python modules. It can be used in any web/data-server to get live status
|
|
9
|
+
about the running server. Here is an example
|
|
10
|
+
|
|
11
|
+
.. doctest:
|
|
12
|
+
|
|
13
|
+
from Utils.procstats import status threadStack
|
|
14
|
+
|
|
15
|
+
class SomeServer(object):
|
|
16
|
+
def __init__(self):
|
|
17
|
+
self.time0 = time.time()
|
|
18
|
+
def status(self):
|
|
19
|
+
sdict = {'server': processStatus()}
|
|
20
|
+
sdict['server'].update({'uptime': time.time()-self.time0})
|
|
21
|
+
sdict.update(threadStack())
|
|
22
|
+
return sdict
|
|
23
|
+
|
|
24
|
+
The exposed status endpoint will return a json dictionary containing server
|
|
25
|
+
upteima and cpu/mem/threads information.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
# system modules
|
|
29
|
+
import os
|
|
30
|
+
import sys
|
|
31
|
+
import json
|
|
32
|
+
import time
|
|
33
|
+
import argparse
|
|
34
|
+
import threading
|
|
35
|
+
import traceback
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
import psutil
|
|
39
|
+
except ImportError:
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
def _baseProcessStatusFormat(pid=None):
|
|
43
|
+
if not pid:
|
|
44
|
+
pid = os.getpid()
|
|
45
|
+
ttime = time.localtime()
|
|
46
|
+
tstamp = time.strftime('%d/%b/%Y:%H:%M:%S', ttime)
|
|
47
|
+
return {'pid': pid, 'timestamp': tstamp, 'time': time.time()}
|
|
48
|
+
|
|
49
|
+
def processStatus(pid=None):
|
|
50
|
+
"Return status of the process in a dictionary format"
|
|
51
|
+
|
|
52
|
+
pdict = _baseProcessStatusFormat(pid)
|
|
53
|
+
if 'psutil' not in sys.modules:
|
|
54
|
+
return pdict
|
|
55
|
+
proc = psutil.Process(pid)
|
|
56
|
+
pdict.update(proc.as_dict())
|
|
57
|
+
return pdict
|
|
58
|
+
|
|
59
|
+
def processStatusDict(pid=None):
|
|
60
|
+
"Return status of the process in a dictionary format"
|
|
61
|
+
pdict = _baseProcessStatusFormat(pid)
|
|
62
|
+
if 'psutil' not in sys.modules:
|
|
63
|
+
return pdict
|
|
64
|
+
proc = psutil.Process(pid)
|
|
65
|
+
pdict.update({"cpu_times": dict(proc.cpu_times()._asdict())})
|
|
66
|
+
pdict.update({"cpu_percent": proc.cpu_percent(interval=1.0)})
|
|
67
|
+
pdict.update({"cpu_num": proc.cpu_num()})
|
|
68
|
+
pdict.update({"memory_full_info": dict(proc.memory_full_info()._asdict())})
|
|
69
|
+
pdict.update({"memory_percent": proc.memory_percent()})
|
|
70
|
+
return pdict
|
|
71
|
+
|
|
72
|
+
def threadStack():
|
|
73
|
+
"""
|
|
74
|
+
Return context of all threads in dictionary format where individual
|
|
75
|
+
thread information stored in its own dicts and all threads are groupped
|
|
76
|
+
into threads list. Code based on example from StackOverflow:
|
|
77
|
+
http://stackoverflow.com/questions/132058/showing-the-stack-trace-from-a-running-python-application
|
|
78
|
+
"""
|
|
79
|
+
tdict = {}
|
|
80
|
+
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
|
|
81
|
+
threads = []
|
|
82
|
+
for tid, stack in list(sys._current_frames().items()):
|
|
83
|
+
tdict = {"thead": id2name.get(tid, ""), "thead_id": tid}
|
|
84
|
+
stacklist = []
|
|
85
|
+
for filename, lineno, name, line in traceback.extract_stack(stack):
|
|
86
|
+
sdict = dict(filename=filename, line_number=lineno, name=name, line=line)
|
|
87
|
+
stacklist.append(sdict)
|
|
88
|
+
tdict.update({"stack": stacklist})
|
|
89
|
+
threads.append(tdict)
|
|
90
|
+
return dict(threads=threads)
|
|
91
|
+
|
|
92
|
+
def main():
|
|
93
|
+
"Main function to use this module as a stand-along script."
|
|
94
|
+
parser = argparse.ArgumentParser(prog='PROG')
|
|
95
|
+
parser.add_argument("--pid", action="store", dest="pid", help="process id")
|
|
96
|
+
opts = parser.parse_args()
|
|
97
|
+
|
|
98
|
+
pdict = processStatus(int(opts.pid))
|
|
99
|
+
pdict.update(threadStack())
|
|
100
|
+
print(json.dumps(pdict))
|
|
101
|
+
|
|
102
|
+
if __name__ == '__main__':
|
|
103
|
+
main()
|
Utils/PythonVersion.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Easily get the version of the python interpreter at runtime
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# Jenkins CI
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import pickle
|
|
9
|
+
|
|
10
|
+
PY3 = sys.version_info[0] == 3
|
|
11
|
+
PY2 = sys.version_info[0] == 2
|
|
12
|
+
|
|
13
|
+
# We need to keep compatibility between multiple python versions
|
|
14
|
+
# Further details at: https://github.com/dmwm/WMCore/pull/10726
|
|
15
|
+
# For PY2: set highest protocol to 2
|
|
16
|
+
# For PY3: set highest protocol to 4 (compatible with python3.6 and python3.8)
|
|
17
|
+
HIGHEST_PICKLE_PROTOCOL = pickle.HIGHEST_PROTOCOL if PY2 else 4
|
Utils/Signals.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
#-*- coding: utf-8 -*-
|
|
3
|
+
#pylint: disable=
|
|
4
|
+
"""
|
|
5
|
+
File : Signals.py
|
|
6
|
+
Author : Valentin Kuznetsov <vkuznet AT gmail dot com>
|
|
7
|
+
Description: This module provide set of hooks to running program
|
|
8
|
+
The dumpthreads callback function will be called every time when
|
|
9
|
+
running program will receive SIGUSR1 signal. E.g., in unix shell
|
|
10
|
+
just do
|
|
11
|
+
shell# kill -s SIGUSR1 <pid>
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
# system modules
|
|
15
|
+
import sys
|
|
16
|
+
import signal
|
|
17
|
+
import threading
|
|
18
|
+
import traceback
|
|
19
|
+
|
|
20
|
+
def dumpthreads(isignal, iframe):
|
|
21
|
+
"""
|
|
22
|
+
Dump context of all threads upon given signal
|
|
23
|
+
http://stackoverflow.com/questions/132058/showing-the-stack-trace-from-a-running-python-application
|
|
24
|
+
"""
|
|
25
|
+
print("DAS stack, signal=%s, frame=%s" % (isignal, iframe))
|
|
26
|
+
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
|
|
27
|
+
code = []
|
|
28
|
+
for tid, stack in list(sys._current_frames().items()):
|
|
29
|
+
code.append("\n# Thread: %s(%d)" % (id2name.get(tid,""), tid))
|
|
30
|
+
for filename, lineno, name, line in traceback.extract_stack(stack):
|
|
31
|
+
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
|
|
32
|
+
if line:
|
|
33
|
+
code.append(" %s" % (line.strip()))
|
|
34
|
+
print("\n".join(code))
|
|
35
|
+
|
|
36
|
+
signal.signal(signal.SIGUSR1, dumpthreads)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@contextlib.contextmanager
|
|
8
|
+
def tmpEnv(**environ):
|
|
9
|
+
"""
|
|
10
|
+
Temporarily set the process environment variables.
|
|
11
|
+
|
|
12
|
+
>>> with tmpEnv(PLUGINS_DIR=u'test/plugins'):
|
|
13
|
+
... "PLUGINS_DIR" in os.environ
|
|
14
|
+
True
|
|
15
|
+
|
|
16
|
+
>>> "PLUGINS_DIR" in os.environ
|
|
17
|
+
False
|
|
18
|
+
|
|
19
|
+
:param environ: Environment variables to set
|
|
20
|
+
"""
|
|
21
|
+
oldEnviron = dict(os.environ)
|
|
22
|
+
os.environ.update(environ)
|
|
23
|
+
try:
|
|
24
|
+
yield
|
|
25
|
+
finally:
|
|
26
|
+
os.environ.clear()
|
|
27
|
+
os.environ.update(oldEnviron)
|