wmglobalqueue 2.3.10rc10__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.

Files changed (345) hide show
  1. Utils/CPMetrics.py +270 -0
  2. Utils/CertTools.py +62 -0
  3. Utils/EmailAlert.py +50 -0
  4. Utils/ExtendedUnitTestCase.py +62 -0
  5. Utils/FileTools.py +182 -0
  6. Utils/IteratorTools.py +80 -0
  7. Utils/MathUtils.py +31 -0
  8. Utils/MemoryCache.py +119 -0
  9. Utils/Patterns.py +24 -0
  10. Utils/Pipeline.py +137 -0
  11. Utils/PortForward.py +97 -0
  12. Utils/ProcessStats.py +103 -0
  13. Utils/PythonVersion.py +17 -0
  14. Utils/Signals.py +36 -0
  15. Utils/TemporaryEnvironment.py +27 -0
  16. Utils/Throttled.py +227 -0
  17. Utils/Timers.py +130 -0
  18. Utils/Timestamps.py +86 -0
  19. Utils/TokenManager.py +143 -0
  20. Utils/Tracing.py +60 -0
  21. Utils/TwPrint.py +98 -0
  22. Utils/Utilities.py +308 -0
  23. Utils/__init__.py +11 -0
  24. WMCore/ACDC/Collection.py +57 -0
  25. WMCore/ACDC/CollectionTypes.py +12 -0
  26. WMCore/ACDC/CouchCollection.py +67 -0
  27. WMCore/ACDC/CouchFileset.py +238 -0
  28. WMCore/ACDC/CouchService.py +73 -0
  29. WMCore/ACDC/DataCollectionService.py +485 -0
  30. WMCore/ACDC/Fileset.py +94 -0
  31. WMCore/ACDC/__init__.py +11 -0
  32. WMCore/Algorithms/Alarm.py +39 -0
  33. WMCore/Algorithms/MathAlgos.py +274 -0
  34. WMCore/Algorithms/MiscAlgos.py +67 -0
  35. WMCore/Algorithms/ParseXMLFile.py +115 -0
  36. WMCore/Algorithms/Permissions.py +27 -0
  37. WMCore/Algorithms/Singleton.py +58 -0
  38. WMCore/Algorithms/SubprocessAlgos.py +129 -0
  39. WMCore/Algorithms/__init__.py +7 -0
  40. WMCore/Cache/GenericDataCache.py +98 -0
  41. WMCore/Cache/WMConfigCache.py +572 -0
  42. WMCore/Cache/__init__.py +0 -0
  43. WMCore/Configuration.py +651 -0
  44. WMCore/DAOFactory.py +47 -0
  45. WMCore/DataStructs/File.py +177 -0
  46. WMCore/DataStructs/Fileset.py +140 -0
  47. WMCore/DataStructs/Job.py +182 -0
  48. WMCore/DataStructs/JobGroup.py +142 -0
  49. WMCore/DataStructs/JobPackage.py +49 -0
  50. WMCore/DataStructs/LumiList.py +734 -0
  51. WMCore/DataStructs/Mask.py +219 -0
  52. WMCore/DataStructs/MathStructs/ContinuousSummaryHistogram.py +197 -0
  53. WMCore/DataStructs/MathStructs/DiscreteSummaryHistogram.py +92 -0
  54. WMCore/DataStructs/MathStructs/SummaryHistogram.py +117 -0
  55. WMCore/DataStructs/MathStructs/__init__.py +0 -0
  56. WMCore/DataStructs/Pickleable.py +24 -0
  57. WMCore/DataStructs/Run.py +256 -0
  58. WMCore/DataStructs/Subscription.py +175 -0
  59. WMCore/DataStructs/WMObject.py +47 -0
  60. WMCore/DataStructs/WorkUnit.py +112 -0
  61. WMCore/DataStructs/Workflow.py +60 -0
  62. WMCore/DataStructs/__init__.py +8 -0
  63. WMCore/Database/CMSCouch.py +1349 -0
  64. WMCore/Database/ConfigDBMap.py +29 -0
  65. WMCore/Database/CouchUtils.py +118 -0
  66. WMCore/Database/DBCore.py +198 -0
  67. WMCore/Database/DBCreator.py +113 -0
  68. WMCore/Database/DBExceptionHandler.py +57 -0
  69. WMCore/Database/DBFactory.py +110 -0
  70. WMCore/Database/DBFormatter.py +177 -0
  71. WMCore/Database/Dialects.py +13 -0
  72. WMCore/Database/ExecuteDAO.py +327 -0
  73. WMCore/Database/MongoDB.py +241 -0
  74. WMCore/Database/MySQL/Destroy.py +42 -0
  75. WMCore/Database/MySQL/ListUserContent.py +20 -0
  76. WMCore/Database/MySQL/__init__.py +9 -0
  77. WMCore/Database/MySQLCore.py +132 -0
  78. WMCore/Database/Oracle/Destroy.py +56 -0
  79. WMCore/Database/Oracle/ListUserContent.py +19 -0
  80. WMCore/Database/Oracle/__init__.py +9 -0
  81. WMCore/Database/ResultSet.py +44 -0
  82. WMCore/Database/Transaction.py +91 -0
  83. WMCore/Database/__init__.py +9 -0
  84. WMCore/Database/ipy_profile_couch.py +438 -0
  85. WMCore/GlobalWorkQueue/CherryPyThreads/CleanUpTask.py +29 -0
  86. WMCore/GlobalWorkQueue/CherryPyThreads/HeartbeatMonitor.py +105 -0
  87. WMCore/GlobalWorkQueue/CherryPyThreads/LocationUpdateTask.py +28 -0
  88. WMCore/GlobalWorkQueue/CherryPyThreads/ReqMgrInteractionTask.py +35 -0
  89. WMCore/GlobalWorkQueue/CherryPyThreads/__init__.py +0 -0
  90. WMCore/GlobalWorkQueue/__init__.py +0 -0
  91. WMCore/GroupUser/CouchObject.py +127 -0
  92. WMCore/GroupUser/Decorators.py +51 -0
  93. WMCore/GroupUser/Group.py +33 -0
  94. WMCore/GroupUser/Interface.py +73 -0
  95. WMCore/GroupUser/User.py +96 -0
  96. WMCore/GroupUser/__init__.py +11 -0
  97. WMCore/Lexicon.py +836 -0
  98. WMCore/REST/Auth.py +202 -0
  99. WMCore/REST/CherryPyPeriodicTask.py +166 -0
  100. WMCore/REST/Error.py +333 -0
  101. WMCore/REST/Format.py +642 -0
  102. WMCore/REST/HeartbeatMonitorBase.py +90 -0
  103. WMCore/REST/Main.py +623 -0
  104. WMCore/REST/Server.py +2435 -0
  105. WMCore/REST/Services.py +24 -0
  106. WMCore/REST/Test.py +120 -0
  107. WMCore/REST/Tools.py +38 -0
  108. WMCore/REST/Validation.py +250 -0
  109. WMCore/REST/__init__.py +1 -0
  110. WMCore/ReqMgr/DataStructs/RequestStatus.py +209 -0
  111. WMCore/ReqMgr/DataStructs/RequestType.py +13 -0
  112. WMCore/ReqMgr/DataStructs/__init__.py +0 -0
  113. WMCore/ReqMgr/__init__.py +1 -0
  114. WMCore/Services/AlertManager/AlertManagerAPI.py +111 -0
  115. WMCore/Services/AlertManager/__init__.py +0 -0
  116. WMCore/Services/CRIC/CRIC.py +238 -0
  117. WMCore/Services/CRIC/__init__.py +0 -0
  118. WMCore/Services/DBS/DBS3Reader.py +1044 -0
  119. WMCore/Services/DBS/DBSConcurrency.py +44 -0
  120. WMCore/Services/DBS/DBSErrors.py +113 -0
  121. WMCore/Services/DBS/DBSReader.py +23 -0
  122. WMCore/Services/DBS/DBSUtils.py +139 -0
  123. WMCore/Services/DBS/DBSWriterObjects.py +381 -0
  124. WMCore/Services/DBS/ProdException.py +133 -0
  125. WMCore/Services/DBS/__init__.py +8 -0
  126. WMCore/Services/FWJRDB/FWJRDBAPI.py +118 -0
  127. WMCore/Services/FWJRDB/__init__.py +0 -0
  128. WMCore/Services/HTTPS/HTTPSAuthHandler.py +66 -0
  129. WMCore/Services/HTTPS/__init__.py +0 -0
  130. WMCore/Services/LogDB/LogDB.py +201 -0
  131. WMCore/Services/LogDB/LogDBBackend.py +191 -0
  132. WMCore/Services/LogDB/LogDBExceptions.py +11 -0
  133. WMCore/Services/LogDB/LogDBReport.py +85 -0
  134. WMCore/Services/LogDB/__init__.py +0 -0
  135. WMCore/Services/MSPileup/__init__.py +0 -0
  136. WMCore/Services/MSUtils/MSUtils.py +54 -0
  137. WMCore/Services/MSUtils/__init__.py +0 -0
  138. WMCore/Services/McM/McM.py +173 -0
  139. WMCore/Services/McM/__init__.py +8 -0
  140. WMCore/Services/MonIT/Grafana.py +133 -0
  141. WMCore/Services/MonIT/__init__.py +0 -0
  142. WMCore/Services/PyCondor/PyCondorAPI.py +154 -0
  143. WMCore/Services/PyCondor/PyCondorUtils.py +105 -0
  144. WMCore/Services/PyCondor/__init__.py +0 -0
  145. WMCore/Services/ReqMgr/ReqMgr.py +261 -0
  146. WMCore/Services/ReqMgr/__init__.py +0 -0
  147. WMCore/Services/ReqMgrAux/ReqMgrAux.py +419 -0
  148. WMCore/Services/ReqMgrAux/__init__.py +0 -0
  149. WMCore/Services/RequestDB/RequestDBReader.py +267 -0
  150. WMCore/Services/RequestDB/RequestDBWriter.py +39 -0
  151. WMCore/Services/RequestDB/__init__.py +0 -0
  152. WMCore/Services/Requests.py +624 -0
  153. WMCore/Services/Rucio/Rucio.py +1287 -0
  154. WMCore/Services/Rucio/RucioUtils.py +74 -0
  155. WMCore/Services/Rucio/__init__.py +0 -0
  156. WMCore/Services/RucioConMon/RucioConMon.py +128 -0
  157. WMCore/Services/RucioConMon/__init__.py +0 -0
  158. WMCore/Services/Service.py +400 -0
  159. WMCore/Services/StompAMQ/__init__.py +0 -0
  160. WMCore/Services/TagCollector/TagCollector.py +155 -0
  161. WMCore/Services/TagCollector/XMLUtils.py +98 -0
  162. WMCore/Services/TagCollector/__init__.py +0 -0
  163. WMCore/Services/UUIDLib.py +13 -0
  164. WMCore/Services/UserFileCache/UserFileCache.py +160 -0
  165. WMCore/Services/UserFileCache/__init__.py +8 -0
  166. WMCore/Services/WMAgent/WMAgent.py +63 -0
  167. WMCore/Services/WMAgent/__init__.py +0 -0
  168. WMCore/Services/WMArchive/CMSSWMetrics.py +526 -0
  169. WMCore/Services/WMArchive/DataMap.py +463 -0
  170. WMCore/Services/WMArchive/WMArchive.py +33 -0
  171. WMCore/Services/WMArchive/__init__.py +0 -0
  172. WMCore/Services/WMBS/WMBS.py +97 -0
  173. WMCore/Services/WMBS/__init__.py +0 -0
  174. WMCore/Services/WMStats/DataStruct/RequestInfoCollection.py +300 -0
  175. WMCore/Services/WMStats/DataStruct/__init__.py +0 -0
  176. WMCore/Services/WMStats/WMStatsPycurl.py +145 -0
  177. WMCore/Services/WMStats/WMStatsReader.py +445 -0
  178. WMCore/Services/WMStats/WMStatsWriter.py +273 -0
  179. WMCore/Services/WMStats/__init__.py +0 -0
  180. WMCore/Services/WMStatsServer/WMStatsServer.py +134 -0
  181. WMCore/Services/WMStatsServer/__init__.py +0 -0
  182. WMCore/Services/WorkQueue/WorkQueue.py +492 -0
  183. WMCore/Services/WorkQueue/__init__.py +0 -0
  184. WMCore/Services/__init__.py +8 -0
  185. WMCore/Services/pycurl_manager.py +574 -0
  186. WMCore/WMBase.py +50 -0
  187. WMCore/WMConnectionBase.py +164 -0
  188. WMCore/WMException.py +183 -0
  189. WMCore/WMExceptions.py +269 -0
  190. WMCore/WMFactory.py +76 -0
  191. WMCore/WMInit.py +228 -0
  192. WMCore/WMLogging.py +108 -0
  193. WMCore/WMSpec/ConfigSectionTree.py +442 -0
  194. WMCore/WMSpec/Persistency.py +135 -0
  195. WMCore/WMSpec/Steps/BuildMaster.py +87 -0
  196. WMCore/WMSpec/Steps/BuildTools.py +201 -0
  197. WMCore/WMSpec/Steps/Builder.py +97 -0
  198. WMCore/WMSpec/Steps/Diagnostic.py +89 -0
  199. WMCore/WMSpec/Steps/Emulator.py +62 -0
  200. WMCore/WMSpec/Steps/ExecuteMaster.py +208 -0
  201. WMCore/WMSpec/Steps/Executor.py +210 -0
  202. WMCore/WMSpec/Steps/StepFactory.py +213 -0
  203. WMCore/WMSpec/Steps/TaskEmulator.py +75 -0
  204. WMCore/WMSpec/Steps/Template.py +204 -0
  205. WMCore/WMSpec/Steps/Templates/AlcaHarvest.py +76 -0
  206. WMCore/WMSpec/Steps/Templates/CMSSW.py +613 -0
  207. WMCore/WMSpec/Steps/Templates/DQMUpload.py +59 -0
  208. WMCore/WMSpec/Steps/Templates/DeleteFiles.py +70 -0
  209. WMCore/WMSpec/Steps/Templates/LogArchive.py +84 -0
  210. WMCore/WMSpec/Steps/Templates/LogCollect.py +105 -0
  211. WMCore/WMSpec/Steps/Templates/StageOut.py +105 -0
  212. WMCore/WMSpec/Steps/Templates/__init__.py +10 -0
  213. WMCore/WMSpec/Steps/WMExecutionFailure.py +21 -0
  214. WMCore/WMSpec/Steps/__init__.py +8 -0
  215. WMCore/WMSpec/Utilities.py +63 -0
  216. WMCore/WMSpec/WMSpecErrors.py +12 -0
  217. WMCore/WMSpec/WMStep.py +347 -0
  218. WMCore/WMSpec/WMTask.py +1980 -0
  219. WMCore/WMSpec/WMWorkload.py +2288 -0
  220. WMCore/WMSpec/WMWorkloadTools.py +370 -0
  221. WMCore/WMSpec/__init__.py +9 -0
  222. WMCore/WorkQueue/DataLocationMapper.py +269 -0
  223. WMCore/WorkQueue/DataStructs/ACDCBlock.py +47 -0
  224. WMCore/WorkQueue/DataStructs/Block.py +48 -0
  225. WMCore/WorkQueue/DataStructs/CouchWorkQueueElement.py +148 -0
  226. WMCore/WorkQueue/DataStructs/WorkQueueElement.py +274 -0
  227. WMCore/WorkQueue/DataStructs/WorkQueueElementResult.py +152 -0
  228. WMCore/WorkQueue/DataStructs/WorkQueueElementsSummary.py +185 -0
  229. WMCore/WorkQueue/DataStructs/__init__.py +0 -0
  230. WMCore/WorkQueue/Policy/End/EndPolicyInterface.py +44 -0
  231. WMCore/WorkQueue/Policy/End/SingleShot.py +22 -0
  232. WMCore/WorkQueue/Policy/End/__init__.py +32 -0
  233. WMCore/WorkQueue/Policy/PolicyInterface.py +17 -0
  234. WMCore/WorkQueue/Policy/Start/Block.py +258 -0
  235. WMCore/WorkQueue/Policy/Start/Dataset.py +180 -0
  236. WMCore/WorkQueue/Policy/Start/MonteCarlo.py +131 -0
  237. WMCore/WorkQueue/Policy/Start/ResubmitBlock.py +171 -0
  238. WMCore/WorkQueue/Policy/Start/StartPolicyInterface.py +316 -0
  239. WMCore/WorkQueue/Policy/Start/__init__.py +34 -0
  240. WMCore/WorkQueue/Policy/__init__.py +57 -0
  241. WMCore/WorkQueue/WMBSHelper.py +772 -0
  242. WMCore/WorkQueue/WorkQueue.py +1237 -0
  243. WMCore/WorkQueue/WorkQueueBackend.py +741 -0
  244. WMCore/WorkQueue/WorkQueueBase.py +39 -0
  245. WMCore/WorkQueue/WorkQueueExceptions.py +44 -0
  246. WMCore/WorkQueue/WorkQueueReqMgrInterface.py +278 -0
  247. WMCore/WorkQueue/WorkQueueUtils.py +130 -0
  248. WMCore/WorkQueue/__init__.py +13 -0
  249. WMCore/Wrappers/JsonWrapper/JSONThunker.py +342 -0
  250. WMCore/Wrappers/JsonWrapper/__init__.py +7 -0
  251. WMCore/Wrappers/__init__.py +6 -0
  252. WMCore/__init__.py +10 -0
  253. wmglobalqueue-2.3.10rc10.data/data/bin/wmc-dist-patch +15 -0
  254. wmglobalqueue-2.3.10rc10.data/data/bin/wmc-dist-unpatch +8 -0
  255. wmglobalqueue-2.3.10rc10.data/data/bin/wmc-httpd +3 -0
  256. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/.couchapprc +1 -0
  257. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/README.md +40 -0
  258. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/_attachments/index.html +264 -0
  259. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/_attachments/js/ElementInfoByWorkflow.js +96 -0
  260. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/_attachments/js/StuckElementInfo.js +57 -0
  261. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/_attachments/js/WorkloadInfoTable.js +80 -0
  262. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/_attachments/js/dataTable.js +70 -0
  263. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/_attachments/js/namespace.js +23 -0
  264. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/_attachments/style/main.css +75 -0
  265. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/couchapp.json +4 -0
  266. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/filters/childQueueFilter.js +13 -0
  267. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/filters/filterDeletedDocs.js +3 -0
  268. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/filters/queueFilter.js +11 -0
  269. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/language +1 -0
  270. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/lib/mustache.js +333 -0
  271. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/lib/validate.js +27 -0
  272. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/lib/workqueue_utils.js +61 -0
  273. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/lists/elementsDetail.js +28 -0
  274. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/lists/filter.js +86 -0
  275. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/lists/stuckElements.js +38 -0
  276. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/lists/workRestrictions.js +153 -0
  277. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/lists/workflowSummary.js +28 -0
  278. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/rewrites.json +73 -0
  279. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/shows/redirect.js +23 -0
  280. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/shows/status.js +40 -0
  281. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/templates/ElementSummaryByWorkflow.html +27 -0
  282. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/templates/StuckElementSummary.html +26 -0
  283. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/templates/TaskStatus.html +23 -0
  284. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/templates/WorkflowSummary.html +27 -0
  285. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/templates/partials/workqueue-common-lib.html +2 -0
  286. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib-remote.html +16 -0
  287. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib.html +18 -0
  288. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/updates/in-place.js +50 -0
  289. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/validate_doc_update.js +8 -0
  290. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.couch.app.js +235 -0
  291. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.pathbinder.js +173 -0
  292. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/activeData/map.js +8 -0
  293. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/activeData/reduce.js +2 -0
  294. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/activeParentData/map.js +8 -0
  295. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/activeParentData/reduce.js +2 -0
  296. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/activePileupData/map.js +8 -0
  297. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/activePileupData/reduce.js +2 -0
  298. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/analyticsData/map.js +11 -0
  299. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/analyticsData/reduce.js +1 -0
  300. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/availableByPriority/map.js +6 -0
  301. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/conflicts/map.js +5 -0
  302. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elements/map.js +5 -0
  303. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elementsByData/map.js +8 -0
  304. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elementsByParent/map.js +8 -0
  305. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elementsByParentData/map.js +8 -0
  306. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elementsByPileupData/map.js +8 -0
  307. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elementsByStatus/map.js +8 -0
  308. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elementsBySubscription/map.js +6 -0
  309. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/map.js +8 -0
  310. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/reduce.js +3 -0
  311. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/elementsDetailByWorkflowAndStatus/map.js +26 -0
  312. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/map.js +10 -0
  313. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/reduce.js +1 -0
  314. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/map.js +6 -0
  315. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/reduce.js +1 -0
  316. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/map.js +6 -0
  317. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/reduce.js +1 -0
  318. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/map.js +6 -0
  319. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/reduce.js +1 -0
  320. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByRequest/map.js +6 -0
  321. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByRequest/reduce.js +1 -0
  322. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByStatus/map.js +6 -0
  323. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByStatus/reduce.js +1 -0
  324. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/map.js +6 -0
  325. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/reduce.js +1 -0
  326. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/openRequests/map.js +6 -0
  327. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/recent-items/map.js +5 -0
  328. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/map.js +6 -0
  329. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/reduce.js +1 -0
  330. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/specsByWorkflow/map.js +5 -0
  331. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/stuckElements/map.js +38 -0
  332. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/map.js +12 -0
  333. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/reduce.js +3 -0
  334. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/wmbsUrl/map.js +6 -0
  335. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/wmbsUrl/reduce.js +2 -0
  336. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/map.js +6 -0
  337. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/reduce.js +2 -0
  338. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/workflowSummary/map.js +9 -0
  339. wmglobalqueue-2.3.10rc10.data/data/data/couchapps/WorkQueue/views/workflowSummary/reduce.js +10 -0
  340. wmglobalqueue-2.3.10rc10.dist-info/METADATA +26 -0
  341. wmglobalqueue-2.3.10rc10.dist-info/RECORD +345 -0
  342. wmglobalqueue-2.3.10rc10.dist-info/WHEEL +5 -0
  343. wmglobalqueue-2.3.10rc10.dist-info/licenses/LICENSE +202 -0
  344. wmglobalqueue-2.3.10rc10.dist-info/licenses/NOTICE +16 -0
  345. wmglobalqueue-2.3.10rc10.dist-info/top_level.txt +2 -0
@@ -0,0 +1,574 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: ISO-8859-1 -*-
3
+ # pylint: disable=R0913,W0702,R0914,R0912,R0201
4
+ """
5
+ File: pycurl_manager.py
6
+ Author: Valentin Kuznetsov <vkuznet@gmail.com>
7
+ Description: a basic wrapper around pycurl library.
8
+ The RequestHandler class provides basic APIs to get data
9
+ from a single resource or submit mutliple requests to
10
+ underlying data-services.
11
+
12
+ Examples:
13
+ # CERN SSO: http://linux.web.cern.ch/linux/docs/cernssocookie.shtml
14
+ # use RequestHandler with CERN SSO enabled site
15
+ mgr = RequestHandler()
16
+ url = "https://cms-gwmsmon.cern.ch/prodview/json/site_summary"
17
+ params = {}
18
+ tfile = tempfile.NamedTemporaryFile()
19
+ cern_sso_cookie(url, tfile.name, cert, ckey)
20
+ cookie = {url: tfile.name}
21
+ header, data = mgr.request(url3, params, cookie=cookie)
22
+ if header.status != 200:
23
+ print "ERROR"
24
+
25
+ # fetch multiple urls at onces from various urls
26
+ tfile = tempfile.NamedTemporaryFile()
27
+ ckey = os.path.join(os.environ['HOME'], '.globus/userkey.pem')
28
+ cert = os.path.join(os.environ['HOME'], '.globus/usercert.pem')
29
+ url1 = "https://cmsweb-prod.cern.ch/dbs/prod/global/DBSReader/help"
30
+ url2 = "https://cmsweb-prod.cern.ch/dbs/prod/global/DBSReader/datatiers"
31
+ url3 = "https://cms-gwmsmon.cern.ch/prodview/json/site_summary"
32
+ cern_sso_cookie(url3, tfile.name, cert, ckey)
33
+ cookie = {url3: tfile.name}
34
+ urls = [url1, url2, url3]
35
+ data = getdata(urls, ckey, cert, cookie=cookie)
36
+ for row in data:
37
+ print(row)
38
+ """
39
+ from __future__ import print_function
40
+ from future import standard_library
41
+ standard_library.install_aliases()
42
+
43
+ from builtins import str, range, object
44
+ from past.builtins import basestring
45
+ from future.utils import viewitems
46
+
47
+
48
+ # system modules
49
+ import copy
50
+ import json
51
+ import gzip
52
+ import logging
53
+ import os
54
+ import re
55
+ import subprocess
56
+ import pycurl
57
+ from io import BytesIO
58
+ import http.client
59
+ from urllib.parse import urlencode
60
+
61
+ from Utils.Utilities import encodeUnicodeToBytes, decodeBytesToUnicode
62
+ from Utils.PortForward import portForward, PortForward
63
+ from Utils.TokenManager import TokenManager
64
+
65
+
66
+ def getException(url, params, headers, header, data):
67
+ """
68
+ Return HTTP exception for a given set of parameters:
69
+ :param url: string
70
+ :param params: dict
71
+ :param headers: dict
72
+ :param header: ResponseHeader
73
+ :param data: HTTP body
74
+ """
75
+ msg = 'url=%s, code=%s, reason=%s, headers=%s, result=%s' \
76
+ % (url, header.status, header.reason, header.header, data)
77
+ exc = http.client.HTTPException(msg)
78
+ setattr(exc, 'req_data', params)
79
+ setattr(exc, 'req_headers', headers)
80
+ setattr(exc, 'url', url)
81
+ setattr(exc, 'result', data)
82
+ setattr(exc, 'status', header.status)
83
+ setattr(exc, 'reason', header.reason)
84
+ setattr(exc, 'headers', header.header)
85
+ return exc
86
+
87
+ def decompress(body, headers):
88
+ """
89
+ Helper function to decompress given body if HTTP headers contains gzip encoding
90
+ :param body: bytes
91
+ :param headers: dict
92
+ :return: decode body
93
+ """
94
+ encoding = ""
95
+ for header, value in headers.items():
96
+ if header.lower() == 'content-encoding' and 'gzip' in value.lower():
97
+ encoding = 'gzip'
98
+ break
99
+ if encoding != 'gzip':
100
+ return body
101
+
102
+ try:
103
+ return gzip.decompress(body)
104
+ except Exception as exc:
105
+ logger = logging.getLogger()
106
+ msg = "While processing decompress function with headers: %s, " % headers
107
+ msg += "we were unable to decompress gzip content. Details: %s. " % str(exc)
108
+ msg += "Considering response body as uncompressed."
109
+ logger.exception(msg)
110
+ return body
111
+
112
+ class ResponseHeader(object):
113
+ """ResponseHeader parses HTTP response header"""
114
+
115
+ def __init__(self, response):
116
+ super(ResponseHeader, self).__init__()
117
+ self.header = {}
118
+ self.reason = ''
119
+ self.fromcache = False
120
+ self.parse(response)
121
+
122
+ def parse(self, response):
123
+ """Parse response header and assign class member data"""
124
+ startRegex = r"^HTTP/(\d|\d.\d) \d{3}" # to match "HTTP/1.1 200" and "HTTP/2 200"
125
+ continueRegex = r"^HTTP/(\d|\d.\d) 100" # Continue: client should continue its request
126
+
127
+ response = decodeBytesToUnicode(response)
128
+
129
+ for row in response.split('\r'):
130
+ row = row.replace('\n', '')
131
+ if not row:
132
+ continue
133
+ if re.search(startRegex, row):
134
+ if re.search(continueRegex, row):
135
+ continue
136
+ # split HTTP header row on empty space
137
+ # for HTTP/proto STATUS REASON
138
+ arr = row.split(' ')
139
+ self.status = int(arr[1])
140
+ self.reason = ' '.join(arr[2:])
141
+ continue
142
+ try:
143
+ key, val = row.split(':', 1)
144
+ self.header[key.strip()] = val.strip()
145
+ except:
146
+ pass
147
+
148
+ def getReason(self):
149
+ """
150
+ Return the HTTP request reason
151
+ """
152
+ return self.reason
153
+
154
+ def getHeader(self):
155
+ """
156
+ Return the header dictionary object
157
+ """
158
+ return self.header
159
+
160
+ def getHeaderKey(self, keyName):
161
+ """
162
+ Provided a key name, return it from the HTTP header.
163
+ Note that - by design - header keys are meant to be
164
+ case insensitive
165
+ :param keyName: a header key name to be looked up
166
+ :return: the value for that header key, or None if not found
167
+ """
168
+ for keyHea, valHea in self.header.items():
169
+ if keyHea.lower() == keyName.lower():
170
+ return valHea
171
+
172
+
173
+ class RequestHandler(object):
174
+ """
175
+ RequestHandler provides APIs to fetch single/multiple
176
+ URL requests based on pycurl library
177
+ """
178
+
179
+ def __init__(self, config=None, logger=None):
180
+ super(RequestHandler, self).__init__()
181
+ if not config:
182
+ config = {}
183
+ defaultOpts = pycurl_options()
184
+ self.nosignal = config.get('nosignal', defaultOpts['NOSIGNAL'])
185
+ self.timeout = config.get('timeout', defaultOpts['TIMEOUT'])
186
+ self.connecttimeout = config.get('connecttimeout', defaultOpts['CONNECTTIMEOUT'])
187
+ self.followlocation = config.get('followlocation', defaultOpts['FOLLOWLOCATION'])
188
+ self.maxredirs = config.get('maxredirs', defaultOpts['MAXREDIRS'])
189
+ self.logger = logger if logger else logging.getLogger()
190
+ self.tokenLocation = config.get('iam_token_file', '')
191
+ if self.tokenLocation:
192
+ self.tmgr = TokenManager(self.tokenLocation)
193
+ else:
194
+ self.tmgr = None
195
+
196
+ def encode_params(self, params, verb, doseq, encode):
197
+ """ Encode request parameters for usage with the 4 verbs.
198
+ Assume params is already encoded if it is a string and
199
+ uses a different encoding depending on the HTTP verb
200
+ (either json.dumps or urllib.urlencode)
201
+ """
202
+ if not encode:
203
+ return params
204
+ # data is already encoded, just return it
205
+ if isinstance(params, basestring):
206
+ return params
207
+
208
+ # data is not encoded, we need to do that
209
+ if verb in ['GET', 'HEAD']:
210
+ if params:
211
+ encoded_data = urlencode(params, doseq=doseq)
212
+ else:
213
+ return ''
214
+ else:
215
+ if params:
216
+ encoded_data = json.dumps(params)
217
+ else:
218
+ return {}
219
+
220
+ return encoded_data
221
+
222
+ def set_opts(self, curl, url, params, headers,
223
+ ckey=None, cert=None, capath=None, verbose=None,
224
+ verb='GET', doseq=True, encode=False, cainfo=None, cookie=None):
225
+ """Set options for given curl object, params should be a dictionary"""
226
+ if not (isinstance(params, (dict, basestring)) or params is None):
227
+ raise TypeError("pycurl parameters should be passed as dictionary or an (encoded) string")
228
+ # ensure the original headers object remains unchanged
229
+ headers = headers or {} # if it's None, then make it a dict
230
+ thisHeaders = copy.deepcopy(headers)
231
+ curl.setopt(pycurl.NOSIGNAL, self.nosignal)
232
+ curl.setopt(pycurl.TIMEOUT, self.timeout)
233
+ curl.setopt(pycurl.CONNECTTIMEOUT, self.connecttimeout)
234
+ curl.setopt(pycurl.FOLLOWLOCATION, self.followlocation)
235
+ curl.setopt(pycurl.MAXREDIRS, self.maxredirs)
236
+
237
+ if cookie and url in cookie:
238
+ curl.setopt(pycurl.COOKIEFILE, cookie[url])
239
+ curl.setopt(pycurl.COOKIEJAR, cookie[url])
240
+
241
+ encoded_data = self.encode_params(params, verb, doseq, encode)
242
+
243
+ if verb == 'GET':
244
+ if encoded_data:
245
+ url = url + '?' + encoded_data
246
+ elif verb == 'HEAD':
247
+ if encoded_data:
248
+ url = url + '?' + encoded_data
249
+ curl.setopt(pycurl.CUSTOMREQUEST, verb)
250
+ curl.setopt(pycurl.HEADER, 1)
251
+ curl.setopt(pycurl.NOBODY, True)
252
+ elif verb == 'POST':
253
+ curl.setopt(pycurl.POST, 1)
254
+ if encoded_data:
255
+ curl.setopt(pycurl.POSTFIELDS, encoded_data)
256
+ elif verb == 'DELETE' or verb == 'PUT':
257
+ curl.setopt(pycurl.CUSTOMREQUEST, verb)
258
+ curl.setopt(pycurl.HTTPHEADER, ['Transfer-Encoding: chunked'])
259
+ if encoded_data:
260
+ curl.setopt(pycurl.POSTFIELDS, encoded_data)
261
+ else:
262
+ raise Exception('Unsupported HTTP method "%s"' % verb)
263
+
264
+ if self.tmgr:
265
+ token = self.tmgr.getToken()
266
+ if token:
267
+ thisHeaders['Authorization'] = 'Bearer {}'.format(token)
268
+
269
+ if verb in ('POST', 'PUT'):
270
+ # only these methods (and PATCH) require this header
271
+ thisHeaders["Content-Length"] = str(len(encoded_data))
272
+
273
+ # we must pass url as a bytes data-type, otherwise pycurl will fail with error
274
+ # TypeError: invalid arguments to setopt
275
+ # see https://curl.haxx.se/mail/curlpython-2007-07/0001.html
276
+ curl.setopt(pycurl.URL, encodeUnicodeToBytes(url))
277
+ # In order to enable service intercommunication with compressed HTTP body,
278
+ # we need to enable this header here, in case it has not been provided by upstream.
279
+ thisHeaders.setdefault("Accept-Encoding", "gzip")
280
+ curl.setopt(pycurl.HTTPHEADER, [encodeUnicodeToBytes("%s: %s" % (k, v)) for k, v in viewitems(thisHeaders)])
281
+
282
+ bbuf = BytesIO()
283
+ hbuf = BytesIO()
284
+ curl.setopt(pycurl.WRITEFUNCTION, bbuf.write)
285
+ curl.setopt(pycurl.HEADERFUNCTION, hbuf.write)
286
+ if capath:
287
+ curl.setopt(pycurl.CAPATH, capath)
288
+ curl.setopt(pycurl.SSL_VERIFYPEER, True)
289
+ if cainfo:
290
+ curl.setopt(pycurl.CAINFO, cainfo)
291
+ else:
292
+ curl.setopt(pycurl.SSL_VERIFYPEER, False)
293
+ if ckey:
294
+ curl.setopt(pycurl.SSLKEY, ckey)
295
+ if cert:
296
+ curl.setopt(pycurl.SSLCERT, cert)
297
+ if verbose:
298
+ curl.setopt(pycurl.VERBOSE, True)
299
+ curl.setopt(pycurl.DEBUGFUNCTION, self.debug)
300
+ return bbuf, hbuf
301
+
302
+ def debug(self, debug_type, debug_msg):
303
+ """Debug callback implementation"""
304
+ print("debug(%d): %s" % (debug_type, debug_msg))
305
+
306
+ def parse_body(self, data, decode=False):
307
+ """
308
+ Parse body part of URL request (by default use json).
309
+ This method can be overwritten.
310
+ """
311
+ if decode:
312
+ try:
313
+ res = json.loads(data)
314
+ return res
315
+ except ValueError as exc:
316
+ msg = 'Unable to load JSON data, %s, data type=%s, pass as is' \
317
+ % (str(exc), type(data))
318
+ logging.debug(msg)
319
+ return data
320
+ else:
321
+ return data
322
+
323
+ def parse_header(self, header):
324
+ """
325
+ Parse response header.
326
+ This method can be overwritten.
327
+ """
328
+ return ResponseHeader(header)
329
+
330
+ @portForward(8443)
331
+ def request(self, url, params, headers=None, verb='GET',
332
+ verbose=0, ckey=None, cert=None, capath=None,
333
+ doseq=True, encode=False, decode=False, cainfo=None, cookie=None):
334
+ """Fetch data for given set of parameters"""
335
+ curl = pycurl.Curl()
336
+ bbuf, hbuf = self.set_opts(curl, url, params, headers, ckey, cert, capath,
337
+ verbose, verb, doseq, encode, cainfo, cookie)
338
+ curl.perform()
339
+ if verbose:
340
+ print(verb, url, params, headers)
341
+ header = self.parse_header(hbuf.getvalue())
342
+ data = bbuf.getvalue()
343
+ data = decompress(data, header.header)
344
+ if header.status < 300:
345
+ if verb == 'HEAD':
346
+ data = ''
347
+ else:
348
+ data = self.parse_body(data, decode)
349
+ else:
350
+ exc = getException(url, params, headers, header, data)
351
+ bbuf.flush()
352
+ hbuf.flush()
353
+ raise exc
354
+
355
+ bbuf.flush()
356
+ hbuf.flush()
357
+ return header, data
358
+
359
+ def getdata(self, url, params, headers=None, verb='GET',
360
+ verbose=0, ckey=None, cert=None, doseq=True,
361
+ encode=False, decode=False, cookie=None):
362
+ """Fetch data for given set of parameters"""
363
+ _, data = self.request(url=url, params=params, headers=headers, verb=verb,
364
+ verbose=verbose, ckey=ckey, cert=cert, doseq=doseq,
365
+ encode=encode, decode=decode, cookie=cookie)
366
+ return data
367
+
368
+ def getheader(self, url, params, headers=None, verb='GET',
369
+ verbose=0, ckey=None, cert=None, doseq=True):
370
+ """Fetch HTTP header"""
371
+ header, _ = self.request(url, params, headers, verb,
372
+ verbose, ckey, cert, doseq=doseq)
373
+ return header
374
+
375
+ @portForward(8443)
376
+ def multirequest(self, url, parray, headers=None, verb='GET',
377
+ ckey=None, cert=None, verbose=None, cookie=None,
378
+ encode=False, decode=False):
379
+ """Fetch data for given set of parameters"""
380
+ multi = pycurl.CurlMulti()
381
+ for params in parray:
382
+ curl = pycurl.Curl()
383
+ bbuf, hbuf = \
384
+ self.set_opts(curl, url, params, headers, ckey=ckey, cert=cert,
385
+ verbose=verbose, cookie=cookie, encode=encode)
386
+ multi.add_handle(curl)
387
+ while True:
388
+ ret, num_handles = multi.perform()
389
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
390
+ break
391
+ while num_handles:
392
+ ret = multi.select(1.0)
393
+ if ret == -1:
394
+ continue
395
+ while True:
396
+ ret, num_handles = multi.perform()
397
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
398
+ break
399
+ dummyNumq, response, dummyErr = multi.info_read()
400
+ for _respItem in response:
401
+ header = self.parse_header(hbuf.getvalue())
402
+ data = bbuf.getvalue()
403
+ data = decompress(data, header.header)
404
+ data = decodeBytesToUnicode(data)
405
+ if header.status < 300:
406
+ if verb == 'HEAD':
407
+ data = ''
408
+ else:
409
+ data = self.parse_body(data, decode)
410
+ else:
411
+ exc = getException(url, params, headers, header, data)
412
+ bbuf.flush()
413
+ hbuf.flush()
414
+ raise exc
415
+ if isinstance(data, dict):
416
+ data.update(params)
417
+ yield data
418
+ if isinstance(data, list):
419
+ for item in data:
420
+ if isinstance(item, dict):
421
+ item.update(params)
422
+ yield item
423
+ else:
424
+ err = 'Unsupported data format: data=%s, type=%s' \
425
+ % (item, type(item))
426
+ raise Exception(err)
427
+ bbuf.flush()
428
+ hbuf.flush()
429
+
430
+
431
+ HTTP_PAT = re.compile( \
432
+ "(https|http)://[-A-Za-z0-9_+&@#/%?=~_|!:,.;]*[-A-Za-z0-9+&@#/%=~_|]")
433
+
434
+
435
+ def validate_url(url):
436
+ "Validate URL"
437
+ if HTTP_PAT.match(url):
438
+ return True
439
+ return False
440
+
441
+
442
+ def pycurl_options():
443
+ "Default set of options for pycurl"
444
+ opts = {
445
+ 'FOLLOWLOCATION': 1,
446
+ 'CONNECTTIMEOUT': 270,
447
+ 'MAXREDIRS': 5,
448
+ 'NOSIGNAL': 1,
449
+ 'TIMEOUT': 270,
450
+ 'SSL_VERIFYPEER': False,
451
+ 'VERBOSE': 0
452
+ }
453
+ return opts
454
+
455
+
456
+ def cern_sso_cookie(url, fname, cert, ckey):
457
+ "Obtain cern SSO cookie and store it in given file name"
458
+ cmd = 'cern-get-sso-cookie -cert %s -key %s -r -u %s -o %s' \
459
+ % (cert, ckey, url, fname)
460
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, env=os.environ)
461
+ proc.wait()
462
+
463
+
464
+ def getdata(urls, ckey, cert, headers=None, options=None, num_conn=50, cookie=None):
465
+ """
466
+ Get data for given list of urls, using provided number of connections
467
+ and user credentials
468
+ """
469
+
470
+ if not options:
471
+ options = pycurl_options()
472
+
473
+ portForwarder = PortForward(8443)
474
+
475
+ # Make a queue with urls
476
+ queue = [portForwarder(u) for u in urls if validate_url(u)]
477
+
478
+ # Check args
479
+ num_urls = len(queue)
480
+ num_conn = min(num_conn, num_urls)
481
+
482
+ # Pre-allocate a list of curl objects
483
+ mcurl = pycurl.CurlMulti()
484
+ mcurl.handles = []
485
+ for _ in range(num_conn):
486
+ curl = pycurl.Curl()
487
+ curl.fp = None
488
+ for key, val in viewitems(options):
489
+ curl.setopt(getattr(pycurl, key), val)
490
+ curl.setopt(pycurl.SSLKEY, ckey)
491
+ curl.setopt(pycurl.SSLCERT, cert)
492
+ mcurl.handles.append(curl)
493
+ if headers:
494
+ curl.setopt(pycurl.HTTPHEADER, \
495
+ ["%s: %s" % (k, v) for k, v in viewitems(headers)])
496
+
497
+ # Main loop
498
+ freelist = mcurl.handles[:]
499
+ num_processed = 0
500
+ while num_processed < num_urls:
501
+ # If there is an url to process and a free curl object,
502
+ # add to multi-stack
503
+ while queue and freelist:
504
+ url = queue.pop(0)
505
+ curl = freelist.pop()
506
+ curl.setopt(pycurl.URL, url.encode('ascii', 'ignore'))
507
+ if cookie and url in cookie:
508
+ curl.setopt(pycurl.COOKIEFILE, cookie[url])
509
+ curl.setopt(pycurl.COOKIEJAR, cookie[url])
510
+ bbuf = BytesIO()
511
+ hbuf = BytesIO()
512
+ curl.setopt(pycurl.WRITEFUNCTION, bbuf.write)
513
+ curl.setopt(pycurl.HEADERFUNCTION, hbuf.write)
514
+ mcurl.add_handle(curl)
515
+ # store some info
516
+ curl.hbuf = hbuf
517
+ curl.bbuf = bbuf
518
+ curl.url = url
519
+ # Run the internal curl state machine for the multi stack
520
+ while True:
521
+ ret, _ = mcurl.perform()
522
+ if ret != pycurl.E_CALL_MULTI_PERFORM:
523
+ break
524
+ # Check for curl objects which have terminated, and add them to the
525
+ # freelist
526
+ while True:
527
+ num_q, ok_list, err_list = mcurl.info_read()
528
+ for curl in ok_list:
529
+ hdrs = decodeBytesToUnicode(curl.hbuf.getvalue())
530
+ data = decompress(decodeBytesToUnicode(curl.bbuf.getvalue()), ResponseHeader(hdrs).getHeader())
531
+ url = curl.url
532
+ curl.bbuf.flush()
533
+ curl.bbuf.close()
534
+ curl.hbuf.close()
535
+ curl.hbuf = None
536
+ curl.bbuf = None
537
+ mcurl.remove_handle(curl)
538
+ freelist.append(curl)
539
+ yield {'url': url, 'data': data, 'headers': hdrs}
540
+ for curl, errno, errmsg in err_list:
541
+ hdrs = curl.hbuf.getvalue()
542
+ data = curl.bbuf.getvalue()
543
+ url = curl.url
544
+ curl.bbuf.flush()
545
+ curl.bbuf.close()
546
+ curl.hbuf.close()
547
+ curl.hbuf = None
548
+ curl.bbuf = None
549
+ mcurl.remove_handle(curl)
550
+ freelist.append(curl)
551
+ yield {'url': url, 'data': None, 'headers': hdrs, \
552
+ 'error': errmsg, 'code': errno}
553
+ num_processed = num_processed + len(ok_list) + len(err_list)
554
+ if num_q == 0:
555
+ break
556
+ # Currently no more I/O is pending, could do something in the meantime
557
+ # (display a progress bar, etc.).
558
+ # We just call select() to sleep until some more data is available.
559
+ mcurl.select(1.0)
560
+
561
+ cleanup(mcurl)
562
+
563
+
564
+ def cleanup(mcurl):
565
+ "Clean-up MultiCurl handles"
566
+ for curl in mcurl.handles:
567
+ if curl.hbuf is not None:
568
+ curl.hbuf.close()
569
+ curl.hbuf = None
570
+ if curl.bbuf is not None:
571
+ curl.bbuf.close()
572
+ curl.bbuf = None
573
+ curl.close()
574
+ mcurl.close()
WMCore/WMBase.py ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env python
2
+ # encoding: utf-8
3
+ """
4
+ WMBase.py
5
+
6
+ Created by Dave Evans on 2011-05-20.
7
+ Copyright (c) 2011 Fermilab. All rights reserved.
8
+ """
9
+
10
+ import sys
11
+ import os
12
+ import os.path
13
+ import inspect
14
+
15
+ def getWMBASE():
16
+ """ returns the root of WMCore install """
17
+ if __file__.find("src/python") != -1:
18
+ return os.path.normpath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
19
+ else:
20
+ return os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
21
+
22
+ def getTestBase(importFlag = True):
23
+ """
24
+ _getTestBase_
25
+
26
+ Returns a base that can be used for testing. Defaults to
27
+ getWMBase if no environment variables WMCORE_TEST_ROOT is defined
28
+ """
29
+ basePath = os.path.normpath(os.path.join(getWMBASE(), 'test/python'))
30
+ envPath = os.environ.get("WMCORE_TEST_ROOT", None)
31
+
32
+ # First, try getting things from the environment
33
+ if envPath != None:
34
+ try:
35
+ if os.path.isdir(envPath):
36
+ return envPath
37
+ except:
38
+ pass
39
+
40
+ if importFlag:
41
+ # Then try importing things from WMCore_t and see if we can
42
+ # find the directory
43
+ try:
44
+ import WMCore_t.__init__ as testImport
45
+ testPath = os.path.dirname(inspect.getsourcefile(testImport))
46
+ return os.path.normpath(os.path.join(testPath, '../'))
47
+ except ImportError:
48
+ pass
49
+
50
+ return basePath