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
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
|
Utils/TwPrint.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
File : TwPrint.py
|
|
4
|
+
|
|
5
|
+
Description:
|
|
6
|
+
|
|
7
|
+
A simple textwrap based printer for nested dictionaries.
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
from textwrap import TextWrapper
|
|
11
|
+
from collections import OrderedDict
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def twClosure(replace_whitespace=False,
|
|
15
|
+
break_long_words=False,
|
|
16
|
+
maxWidth=120,
|
|
17
|
+
maxLength=-1,
|
|
18
|
+
maxDepth=-1,
|
|
19
|
+
initial_indent=''):
|
|
20
|
+
"""
|
|
21
|
+
Deals with indentation of dictionaries with very long key, value pairs.
|
|
22
|
+
replace_whitespace: Replace each whitespace character with a single space.
|
|
23
|
+
break_long_words: If True words longer than width will be broken.
|
|
24
|
+
width: The maximum length of wrapped lines.
|
|
25
|
+
initial_indent: String that will be prepended to the first line of the output
|
|
26
|
+
|
|
27
|
+
Wraps all strings for both keys and values to 120 chars.
|
|
28
|
+
Uses 4 spaces indentation for both keys and values.
|
|
29
|
+
Nested dictionaries and lists go to next line.
|
|
30
|
+
"""
|
|
31
|
+
twr = TextWrapper(replace_whitespace=replace_whitespace,
|
|
32
|
+
break_long_words=break_long_words,
|
|
33
|
+
width=maxWidth,
|
|
34
|
+
initial_indent=initial_indent)
|
|
35
|
+
|
|
36
|
+
def twEnclosed(obj, ind='', depthReached=0, reCall=False):
|
|
37
|
+
"""
|
|
38
|
+
The inner function of the closure
|
|
39
|
+
ind: Initial indentation for the single output string
|
|
40
|
+
reCall: Flag to indicate a recursive call (should not be used outside)
|
|
41
|
+
"""
|
|
42
|
+
output = ''
|
|
43
|
+
if isinstance(obj, dict):
|
|
44
|
+
obj = OrderedDict(sorted(list(obj.items()),
|
|
45
|
+
key=lambda t: t[0],
|
|
46
|
+
reverse=False))
|
|
47
|
+
if reCall:
|
|
48
|
+
output += '\n'
|
|
49
|
+
ind += ' '
|
|
50
|
+
depthReached += 1
|
|
51
|
+
lengthReached = 0
|
|
52
|
+
for key, value in list(obj.items()):
|
|
53
|
+
lengthReached += 1
|
|
54
|
+
if lengthReached > maxLength and maxLength >= 0:
|
|
55
|
+
output += "%s...\n" % ind
|
|
56
|
+
break
|
|
57
|
+
if depthReached <= maxDepth or maxDepth < 0:
|
|
58
|
+
output += "%s%s: %s" % (ind,
|
|
59
|
+
''.join(twr.wrap(key)),
|
|
60
|
+
twEnclosed(value, ind, depthReached=depthReached, reCall=True))
|
|
61
|
+
|
|
62
|
+
elif isinstance(obj, (list, set)):
|
|
63
|
+
if reCall:
|
|
64
|
+
output += '\n'
|
|
65
|
+
ind += ' '
|
|
66
|
+
lengthReached = 0
|
|
67
|
+
for value in obj:
|
|
68
|
+
lengthReached += 1
|
|
69
|
+
if lengthReached > maxLength and maxLength >= 0:
|
|
70
|
+
output += "%s...\n" % ind
|
|
71
|
+
break
|
|
72
|
+
if depthReached <= maxDepth or maxDepth < 0:
|
|
73
|
+
output += "%s%s" % (ind, twEnclosed(value, ind, depthReached=depthReached, reCall=True))
|
|
74
|
+
else:
|
|
75
|
+
output += "%s\n" % str(obj) # join(twr.wrap(str(obj)))
|
|
76
|
+
return output
|
|
77
|
+
|
|
78
|
+
return twEnclosed
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def twPrint(obj, maxWidth=120, maxLength=-1, maxDepth=-1):
|
|
82
|
+
"""
|
|
83
|
+
A simple caller of twClosure (see docstring for twClosure)
|
|
84
|
+
"""
|
|
85
|
+
twPrinter = twClosure(maxWidth=maxWidth,
|
|
86
|
+
maxLength=maxLength,
|
|
87
|
+
maxDepth=maxDepth)
|
|
88
|
+
print(twPrinter(obj))
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def twFormat(obj, maxWidth=120, maxLength=-1, maxDepth=-1):
|
|
92
|
+
"""
|
|
93
|
+
A simple caller of twClosure (see docstring for twClosure)
|
|
94
|
+
"""
|
|
95
|
+
twFormatter = twClosure(maxWidth=maxWidth,
|
|
96
|
+
maxLength=maxLength,
|
|
97
|
+
maxDepth=maxDepth)
|
|
98
|
+
return twFormatter(obj)
|
Utils/Utilities.py
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
|
|
3
|
+
from builtins import str, bytes
|
|
4
|
+
|
|
5
|
+
import subprocess
|
|
6
|
+
import os
|
|
7
|
+
import re
|
|
8
|
+
import zlib
|
|
9
|
+
import base64
|
|
10
|
+
import sys
|
|
11
|
+
from types import ModuleType, FunctionType
|
|
12
|
+
from gc import get_referents
|
|
13
|
+
|
|
14
|
+
import xml.etree.ElementTree as ET
|
|
15
|
+
|
|
16
|
+
def extractFromXML(xmlFile, xmlElement):
|
|
17
|
+
tree = ET.parse(xmlFile)
|
|
18
|
+
root = tree.getroot()
|
|
19
|
+
element = root.find(f".//{xmlElement}")
|
|
20
|
+
if element is not None:
|
|
21
|
+
return element.get("Value")
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
def lowerCmsHeaders(headers):
|
|
25
|
+
"""
|
|
26
|
+
Lower CMS headers in provided header's dict. The WMCore Authentication
|
|
27
|
+
code check only cms headers in lower case, e.g. cms-xxx-yyy.
|
|
28
|
+
"""
|
|
29
|
+
lheaders = {}
|
|
30
|
+
for hkey, hval in list(headers.items()): # perform lower-case
|
|
31
|
+
# lower header keys since we check lower-case in headers
|
|
32
|
+
if hkey.startswith('Cms-') or hkey.startswith('CMS-'):
|
|
33
|
+
lheaders[hkey.lower()] = hval
|
|
34
|
+
else:
|
|
35
|
+
lheaders[hkey] = hval
|
|
36
|
+
return lheaders
|
|
37
|
+
|
|
38
|
+
def makeList(stringList):
|
|
39
|
+
"""
|
|
40
|
+
_makeList_
|
|
41
|
+
|
|
42
|
+
Make a python list out of a comma separated list of strings,
|
|
43
|
+
throws a ValueError if the input is not well formed.
|
|
44
|
+
If the stringList is already of type list, then return it untouched.
|
|
45
|
+
"""
|
|
46
|
+
if isinstance(stringList, list):
|
|
47
|
+
return stringList
|
|
48
|
+
if isinstance(stringList, str):
|
|
49
|
+
toks = stringList.lstrip(' [').rstrip(' ]').split(',')
|
|
50
|
+
if toks == ['']:
|
|
51
|
+
return []
|
|
52
|
+
return [str(tok.strip(' \'"')) for tok in toks]
|
|
53
|
+
raise ValueError("Can't convert to list %s" % stringList)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def makeNonEmptyList(stringList):
|
|
57
|
+
"""
|
|
58
|
+
_makeNonEmptyList_
|
|
59
|
+
|
|
60
|
+
Given a string or a list of strings, return a non empty list of strings.
|
|
61
|
+
Throws an exception in case the final list is empty or input data is not
|
|
62
|
+
a string or a python list
|
|
63
|
+
"""
|
|
64
|
+
finalList = makeList(stringList)
|
|
65
|
+
if not finalList:
|
|
66
|
+
raise ValueError("Input data cannot be an empty list %s" % stringList)
|
|
67
|
+
return finalList
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def strToBool(string):
|
|
71
|
+
"""
|
|
72
|
+
Try to convert different variations of True or False (including a string
|
|
73
|
+
type object) to a boolean value.
|
|
74
|
+
In short:
|
|
75
|
+
* True gets mapped from: True, "True", "true", "TRUE".
|
|
76
|
+
* False gets mapped from: False, "False", "false", "FALSE"
|
|
77
|
+
* anything else will fail
|
|
78
|
+
:param string: expects a boolean or a string, but it could be anything else
|
|
79
|
+
:return: a boolean value, or raise an exception if value passed in is not supported
|
|
80
|
+
"""
|
|
81
|
+
if string is False or string is True:
|
|
82
|
+
return string
|
|
83
|
+
elif string in ["True", "true", "TRUE"]:
|
|
84
|
+
return True
|
|
85
|
+
elif string in ["False", "false", "FALSE"]:
|
|
86
|
+
return False
|
|
87
|
+
raise ValueError("Can't convert to bool: %s" % string)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def safeStr(string):
|
|
91
|
+
"""
|
|
92
|
+
_safeStr_
|
|
93
|
+
|
|
94
|
+
Cast simple data (int, float, basestring) to string.
|
|
95
|
+
"""
|
|
96
|
+
if not isinstance(string, (tuple, list, set, dict)):
|
|
97
|
+
return str(string)
|
|
98
|
+
raise ValueError("We're not supposed to convert %s to string." % string)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def diskUse():
|
|
102
|
+
"""
|
|
103
|
+
This returns the % use of each disk partition
|
|
104
|
+
"""
|
|
105
|
+
diskPercent = []
|
|
106
|
+
df = subprocess.Popen(["df", "-klP"], stdout=subprocess.PIPE)
|
|
107
|
+
output = df.communicate()[0]
|
|
108
|
+
output = decodeBytesToUnicode(output).split("\n")
|
|
109
|
+
for x in output:
|
|
110
|
+
split = x.split()
|
|
111
|
+
if split != [] and split[0] != 'Filesystem':
|
|
112
|
+
diskPercent.append({'filesystem': split[0],
|
|
113
|
+
'mounted': split[5],
|
|
114
|
+
'percent': split[4]})
|
|
115
|
+
|
|
116
|
+
return diskPercent
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def numberCouchProcess():
|
|
120
|
+
"""
|
|
121
|
+
This returns the number of couch process
|
|
122
|
+
"""
|
|
123
|
+
ps = subprocess.Popen(["ps", "-ef"], stdout=subprocess.PIPE)
|
|
124
|
+
process = ps.communicate()[0]
|
|
125
|
+
process = decodeBytesToUnicode(process).count('couchjs')
|
|
126
|
+
|
|
127
|
+
return process
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def rootUrlJoin(base, extend):
|
|
131
|
+
"""
|
|
132
|
+
Adds a path element to the path within a ROOT url
|
|
133
|
+
"""
|
|
134
|
+
if base:
|
|
135
|
+
match = re.match("^root://([^/]+)/(.+)", base)
|
|
136
|
+
if match:
|
|
137
|
+
host = match.group(1)
|
|
138
|
+
path = match.group(2)
|
|
139
|
+
newpath = os.path.join(path, extend)
|
|
140
|
+
newurl = "root://%s/%s" % (host, newpath)
|
|
141
|
+
return newurl
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def zipEncodeStr(message, maxLen=5120, compressLevel=9, steps=100, truncateIndicator=" (...)"):
|
|
146
|
+
"""
|
|
147
|
+
_zipEncodeStr_
|
|
148
|
+
Utility to zip a string and encode it.
|
|
149
|
+
If zipped encoded length is greater than maxLen,
|
|
150
|
+
truncate message until zip/encoded version
|
|
151
|
+
is within the limits allowed.
|
|
152
|
+
"""
|
|
153
|
+
message = encodeUnicodeToBytes(message)
|
|
154
|
+
encodedStr = zlib.compress(message, compressLevel)
|
|
155
|
+
encodedStr = base64.b64encode(encodedStr)
|
|
156
|
+
if len(encodedStr) < maxLen or maxLen == -1:
|
|
157
|
+
return encodedStr
|
|
158
|
+
|
|
159
|
+
compressRate = 1. * len(encodedStr) / len(base64.b64encode(message))
|
|
160
|
+
|
|
161
|
+
# Estimate new length for message zip/encoded version
|
|
162
|
+
# to be less than maxLen.
|
|
163
|
+
# Also, append truncate indicator to message.
|
|
164
|
+
truncateIndicator = encodeUnicodeToBytes(truncateIndicator)
|
|
165
|
+
strLen = int((maxLen - len(truncateIndicator)) / compressRate)
|
|
166
|
+
message = message[:strLen] + truncateIndicator
|
|
167
|
+
|
|
168
|
+
encodedStr = zipEncodeStr(message, maxLen=-1)
|
|
169
|
+
|
|
170
|
+
# If new length is not short enough, truncate
|
|
171
|
+
# recursively by steps
|
|
172
|
+
while len(encodedStr) > maxLen:
|
|
173
|
+
message = message[:-steps - len(truncateIndicator)] + truncateIndicator
|
|
174
|
+
encodedStr = zipEncodeStr(message, maxLen=-1)
|
|
175
|
+
|
|
176
|
+
return encodedStr
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def getSize(obj):
|
|
180
|
+
"""
|
|
181
|
+
_getSize_
|
|
182
|
+
|
|
183
|
+
Function to traverse an object and calculate its total size in bytes
|
|
184
|
+
:param obj: a python object
|
|
185
|
+
:return: an integer representing the total size of the object
|
|
186
|
+
|
|
187
|
+
Code extracted from Stack Overflow:
|
|
188
|
+
https://stackoverflow.com/questions/449560/how-do-i-determine-the-size-of-an-object-in-python
|
|
189
|
+
"""
|
|
190
|
+
# Custom objects know their class.
|
|
191
|
+
# Function objects seem to know way too much, including modules.
|
|
192
|
+
# Exclude modules as well.
|
|
193
|
+
BLACKLIST = type, ModuleType, FunctionType
|
|
194
|
+
|
|
195
|
+
if isinstance(obj, BLACKLIST):
|
|
196
|
+
raise TypeError('getSize() does not take argument of type: '+ str(type(obj)))
|
|
197
|
+
seen_ids = set()
|
|
198
|
+
size = 0
|
|
199
|
+
objects = [obj]
|
|
200
|
+
while objects:
|
|
201
|
+
need_referents = []
|
|
202
|
+
for obj in objects:
|
|
203
|
+
if not isinstance(obj, BLACKLIST) and id(obj) not in seen_ids:
|
|
204
|
+
seen_ids.add(id(obj))
|
|
205
|
+
size += sys.getsizeof(obj)
|
|
206
|
+
need_referents.append(obj)
|
|
207
|
+
objects = get_referents(*need_referents)
|
|
208
|
+
return size
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def decodeBytesToUnicode(value, errors="strict"):
|
|
212
|
+
"""
|
|
213
|
+
Accepts an input "value" of generic type.
|
|
214
|
+
|
|
215
|
+
If "value" is a string of type sequence of bytes (i.e. in py2 `str` or
|
|
216
|
+
`future.types.newbytes.newbytes`, in py3 `bytes`), then it is converted to
|
|
217
|
+
a sequence of unicode codepoints.
|
|
218
|
+
|
|
219
|
+
This function is useful for cleaning input data when using the
|
|
220
|
+
"unicode sandwich" approach, which involves converting bytes (i.e. strings
|
|
221
|
+
of type sequence of bytes) to unicode (i.e. strings of type sequence of
|
|
222
|
+
unicode codepoints, in py2 `unicode` or `future.types.newstr.newstr`,
|
|
223
|
+
in py3 `str` ) as soon as possible when recieving input data, and
|
|
224
|
+
converting unicode back to bytes as late as possible.
|
|
225
|
+
achtung!:
|
|
226
|
+
- converting unicode back to bytes is not covered by this function
|
|
227
|
+
- converting unicode back to bytes is not always necessary. when in doubt,
|
|
228
|
+
do not do it.
|
|
229
|
+
Reference: https://nedbatchelder.com/text/unipain.html
|
|
230
|
+
|
|
231
|
+
py2:
|
|
232
|
+
- "errors" can be: "strict", "ignore", "replace",
|
|
233
|
+
- ref: https://docs.python.org/2/howto/unicode.html#the-unicode-type
|
|
234
|
+
py3:
|
|
235
|
+
- "errors" can be: "strict", "ignore", "replace", "backslashreplace"
|
|
236
|
+
- ref: https://docs.python.org/3/howto/unicode.html#the-string-type
|
|
237
|
+
"""
|
|
238
|
+
if isinstance(value, bytes):
|
|
239
|
+
return value.decode("utf-8", errors)
|
|
240
|
+
return value
|
|
241
|
+
|
|
242
|
+
def decodeBytesToUnicodeConditional(value, errors="ignore", condition=True):
|
|
243
|
+
"""
|
|
244
|
+
if *condition*, then call decodeBytesToUnicode(*value*, *errors*),
|
|
245
|
+
else return *value*
|
|
246
|
+
|
|
247
|
+
This may be useful when we want to conditionally apply decodeBytesToUnicode,
|
|
248
|
+
maintaining brevity.
|
|
249
|
+
|
|
250
|
+
Parameters
|
|
251
|
+
----------
|
|
252
|
+
value : any
|
|
253
|
+
passed to decodeBytesToUnicode
|
|
254
|
+
errors: str
|
|
255
|
+
passed to decodeBytesToUnicode
|
|
256
|
+
condition: boolean of object with attribute __bool__()
|
|
257
|
+
if True, then we run decodeBytesToUnicode. Usually PY2/PY3
|
|
258
|
+
"""
|
|
259
|
+
if condition:
|
|
260
|
+
return decodeBytesToUnicode(value, errors)
|
|
261
|
+
return value
|
|
262
|
+
|
|
263
|
+
def encodeUnicodeToBytes(value, errors="strict"):
|
|
264
|
+
"""
|
|
265
|
+
Accepts an input "value" of generic type.
|
|
266
|
+
|
|
267
|
+
If "value" is a string of type sequence of unicode (i.e. in py2 `unicode` or
|
|
268
|
+
`future.types.newstr.newstr`, in py3 `str`), then it is converted to
|
|
269
|
+
a sequence of bytes.
|
|
270
|
+
|
|
271
|
+
This function is useful for encoding output data when using the
|
|
272
|
+
"unicode sandwich" approach, which involves converting unicode (i.e. strings
|
|
273
|
+
of type sequence of unicode codepoints) to bytes (i.e. strings of type
|
|
274
|
+
sequence of bytes, in py2 `str` or `future.types.newbytes.newbytes`,
|
|
275
|
+
in py3 `bytes`) as late as possible when passing a string to a third-party
|
|
276
|
+
function that only accepts bytes as input (pycurl's curl.setop is an
|
|
277
|
+
example).
|
|
278
|
+
py2:
|
|
279
|
+
- "errors" can be: "strict", "ignore", "replace", "xmlcharrefreplace"
|
|
280
|
+
- ref: https://docs.python.org/2/howto/unicode.html#the-unicode-type
|
|
281
|
+
py3:
|
|
282
|
+
- "errors" can be: "strict", "ignore", "replace", "backslashreplace",
|
|
283
|
+
"xmlcharrefreplace", "namereplace"
|
|
284
|
+
- ref: https://docs.python.org/3/howto/unicode.html#the-string-type
|
|
285
|
+
"""
|
|
286
|
+
if isinstance(value, str):
|
|
287
|
+
return value.encode("utf-8", errors)
|
|
288
|
+
return value
|
|
289
|
+
|
|
290
|
+
def encodeUnicodeToBytesConditional(value, errors="ignore", condition=True):
|
|
291
|
+
"""
|
|
292
|
+
if *condition*, then call encodeUnicodeToBytes(*value*, *errors*),
|
|
293
|
+
else return *value*
|
|
294
|
+
|
|
295
|
+
This may be useful when we want to conditionally apply encodeUnicodeToBytes,
|
|
296
|
+
maintaining brevity.
|
|
297
|
+
|
|
298
|
+
Parameters
|
|
299
|
+
----------
|
|
300
|
+
value : any
|
|
301
|
+
passed to encodeUnicodeToBytes
|
|
302
|
+
errors: str
|
|
303
|
+
passed to encodeUnicodeToBytes
|
|
304
|
+
condition: boolean of object with attribute __bool__()
|
|
305
|
+
if True, then we run encodeUnicodeToBytes. Usually PY2/PY3
|
|
306
|
+
"""
|
|
307
|
+
if condition:
|
|
308
|
+
return encodeUnicodeToBytes(value, errors)
|
|
309
|
+
return value
|
|
310
|
+
|
|
311
|
+
def normalize_spaces(text):
|
|
312
|
+
"""
|
|
313
|
+
Helper function to remove any number of empty spaces within given text and replace
|
|
314
|
+
then with single space.
|
|
315
|
+
:param text: string
|
|
316
|
+
:return: normalized string
|
|
317
|
+
"""
|
|
318
|
+
return re.sub(r'\s+', ' ', text).strip()
|