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.
Files changed (347) hide show
  1. Utils/CPMetrics.py +270 -0
  2. Utils/CertTools.py +100 -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/ProcFS.py +112 -0
  13. Utils/ProcessStats.py +194 -0
  14. Utils/PythonVersion.py +17 -0
  15. Utils/Signals.py +36 -0
  16. Utils/TemporaryEnvironment.py +27 -0
  17. Utils/Throttled.py +227 -0
  18. Utils/Timers.py +130 -0
  19. Utils/Timestamps.py +86 -0
  20. Utils/TokenManager.py +143 -0
  21. Utils/Tracing.py +60 -0
  22. Utils/TwPrint.py +98 -0
  23. Utils/Utilities.py +318 -0
  24. Utils/__init__.py +11 -0
  25. Utils/wmcoreDTools.py +707 -0
  26. WMCore/ACDC/Collection.py +57 -0
  27. WMCore/ACDC/CollectionTypes.py +12 -0
  28. WMCore/ACDC/CouchCollection.py +67 -0
  29. WMCore/ACDC/CouchFileset.py +238 -0
  30. WMCore/ACDC/CouchService.py +73 -0
  31. WMCore/ACDC/DataCollectionService.py +485 -0
  32. WMCore/ACDC/Fileset.py +94 -0
  33. WMCore/ACDC/__init__.py +11 -0
  34. WMCore/Algorithms/Alarm.py +39 -0
  35. WMCore/Algorithms/MathAlgos.py +274 -0
  36. WMCore/Algorithms/MiscAlgos.py +67 -0
  37. WMCore/Algorithms/ParseXMLFile.py +115 -0
  38. WMCore/Algorithms/Permissions.py +27 -0
  39. WMCore/Algorithms/Singleton.py +58 -0
  40. WMCore/Algorithms/SubprocessAlgos.py +129 -0
  41. WMCore/Algorithms/__init__.py +7 -0
  42. WMCore/Cache/GenericDataCache.py +98 -0
  43. WMCore/Cache/WMConfigCache.py +572 -0
  44. WMCore/Cache/__init__.py +0 -0
  45. WMCore/Configuration.py +659 -0
  46. WMCore/DAOFactory.py +47 -0
  47. WMCore/DataStructs/File.py +177 -0
  48. WMCore/DataStructs/Fileset.py +140 -0
  49. WMCore/DataStructs/Job.py +182 -0
  50. WMCore/DataStructs/JobGroup.py +142 -0
  51. WMCore/DataStructs/JobPackage.py +49 -0
  52. WMCore/DataStructs/LumiList.py +734 -0
  53. WMCore/DataStructs/Mask.py +219 -0
  54. WMCore/DataStructs/MathStructs/ContinuousSummaryHistogram.py +197 -0
  55. WMCore/DataStructs/MathStructs/DiscreteSummaryHistogram.py +92 -0
  56. WMCore/DataStructs/MathStructs/SummaryHistogram.py +117 -0
  57. WMCore/DataStructs/MathStructs/__init__.py +0 -0
  58. WMCore/DataStructs/Pickleable.py +24 -0
  59. WMCore/DataStructs/Run.py +256 -0
  60. WMCore/DataStructs/Subscription.py +175 -0
  61. WMCore/DataStructs/WMObject.py +47 -0
  62. WMCore/DataStructs/WorkUnit.py +112 -0
  63. WMCore/DataStructs/Workflow.py +60 -0
  64. WMCore/DataStructs/__init__.py +8 -0
  65. WMCore/Database/CMSCouch.py +1430 -0
  66. WMCore/Database/ConfigDBMap.py +29 -0
  67. WMCore/Database/CouchMonitoring.py +450 -0
  68. WMCore/Database/CouchUtils.py +118 -0
  69. WMCore/Database/DBCore.py +198 -0
  70. WMCore/Database/DBCreator.py +113 -0
  71. WMCore/Database/DBExceptionHandler.py +59 -0
  72. WMCore/Database/DBFactory.py +117 -0
  73. WMCore/Database/DBFormatter.py +177 -0
  74. WMCore/Database/Dialects.py +13 -0
  75. WMCore/Database/ExecuteDAO.py +327 -0
  76. WMCore/Database/MongoDB.py +241 -0
  77. WMCore/Database/MySQL/Destroy.py +42 -0
  78. WMCore/Database/MySQL/ListUserContent.py +20 -0
  79. WMCore/Database/MySQL/__init__.py +9 -0
  80. WMCore/Database/MySQLCore.py +132 -0
  81. WMCore/Database/Oracle/Destroy.py +56 -0
  82. WMCore/Database/Oracle/ListUserContent.py +19 -0
  83. WMCore/Database/Oracle/__init__.py +9 -0
  84. WMCore/Database/ResultSet.py +44 -0
  85. WMCore/Database/Transaction.py +91 -0
  86. WMCore/Database/__init__.py +9 -0
  87. WMCore/Database/ipy_profile_couch.py +438 -0
  88. WMCore/GlobalWorkQueue/CherryPyThreads/CleanUpTask.py +29 -0
  89. WMCore/GlobalWorkQueue/CherryPyThreads/HeartbeatMonitor.py +105 -0
  90. WMCore/GlobalWorkQueue/CherryPyThreads/LocationUpdateTask.py +28 -0
  91. WMCore/GlobalWorkQueue/CherryPyThreads/ReqMgrInteractionTask.py +35 -0
  92. WMCore/GlobalWorkQueue/CherryPyThreads/__init__.py +0 -0
  93. WMCore/GlobalWorkQueue/__init__.py +0 -0
  94. WMCore/GroupUser/CouchObject.py +127 -0
  95. WMCore/GroupUser/Decorators.py +51 -0
  96. WMCore/GroupUser/Group.py +33 -0
  97. WMCore/GroupUser/Interface.py +73 -0
  98. WMCore/GroupUser/User.py +96 -0
  99. WMCore/GroupUser/__init__.py +11 -0
  100. WMCore/Lexicon.py +836 -0
  101. WMCore/REST/Auth.py +202 -0
  102. WMCore/REST/CherryPyPeriodicTask.py +166 -0
  103. WMCore/REST/Error.py +333 -0
  104. WMCore/REST/Format.py +642 -0
  105. WMCore/REST/HeartbeatMonitorBase.py +90 -0
  106. WMCore/REST/Main.py +636 -0
  107. WMCore/REST/Server.py +2435 -0
  108. WMCore/REST/Services.py +24 -0
  109. WMCore/REST/Test.py +120 -0
  110. WMCore/REST/Tools.py +38 -0
  111. WMCore/REST/Validation.py +250 -0
  112. WMCore/REST/__init__.py +1 -0
  113. WMCore/ReqMgr/DataStructs/RequestStatus.py +209 -0
  114. WMCore/ReqMgr/DataStructs/RequestType.py +13 -0
  115. WMCore/ReqMgr/DataStructs/__init__.py +0 -0
  116. WMCore/ReqMgr/__init__.py +1 -0
  117. WMCore/Services/AlertManager/AlertManagerAPI.py +111 -0
  118. WMCore/Services/AlertManager/__init__.py +0 -0
  119. WMCore/Services/CRIC/CRIC.py +238 -0
  120. WMCore/Services/CRIC/__init__.py +0 -0
  121. WMCore/Services/DBS/DBS3Reader.py +1044 -0
  122. WMCore/Services/DBS/DBSConcurrency.py +44 -0
  123. WMCore/Services/DBS/DBSErrors.py +112 -0
  124. WMCore/Services/DBS/DBSReader.py +23 -0
  125. WMCore/Services/DBS/DBSUtils.py +166 -0
  126. WMCore/Services/DBS/DBSWriterObjects.py +381 -0
  127. WMCore/Services/DBS/ProdException.py +133 -0
  128. WMCore/Services/DBS/__init__.py +8 -0
  129. WMCore/Services/FWJRDB/FWJRDBAPI.py +118 -0
  130. WMCore/Services/FWJRDB/__init__.py +0 -0
  131. WMCore/Services/HTTPS/HTTPSAuthHandler.py +66 -0
  132. WMCore/Services/HTTPS/__init__.py +0 -0
  133. WMCore/Services/LogDB/LogDB.py +201 -0
  134. WMCore/Services/LogDB/LogDBBackend.py +191 -0
  135. WMCore/Services/LogDB/LogDBExceptions.py +11 -0
  136. WMCore/Services/LogDB/LogDBReport.py +85 -0
  137. WMCore/Services/LogDB/__init__.py +0 -0
  138. WMCore/Services/MSPileup/__init__.py +0 -0
  139. WMCore/Services/MSUtils/MSUtils.py +54 -0
  140. WMCore/Services/MSUtils/__init__.py +0 -0
  141. WMCore/Services/McM/McM.py +173 -0
  142. WMCore/Services/McM/__init__.py +8 -0
  143. WMCore/Services/MonIT/Grafana.py +133 -0
  144. WMCore/Services/MonIT/__init__.py +0 -0
  145. WMCore/Services/PyCondor/PyCondorAPI.py +154 -0
  146. WMCore/Services/PyCondor/__init__.py +0 -0
  147. WMCore/Services/ReqMgr/ReqMgr.py +261 -0
  148. WMCore/Services/ReqMgr/__init__.py +0 -0
  149. WMCore/Services/ReqMgrAux/ReqMgrAux.py +419 -0
  150. WMCore/Services/ReqMgrAux/__init__.py +0 -0
  151. WMCore/Services/RequestDB/RequestDBReader.py +267 -0
  152. WMCore/Services/RequestDB/RequestDBWriter.py +39 -0
  153. WMCore/Services/RequestDB/__init__.py +0 -0
  154. WMCore/Services/Requests.py +624 -0
  155. WMCore/Services/Rucio/Rucio.py +1290 -0
  156. WMCore/Services/Rucio/RucioUtils.py +74 -0
  157. WMCore/Services/Rucio/__init__.py +0 -0
  158. WMCore/Services/RucioConMon/RucioConMon.py +121 -0
  159. WMCore/Services/RucioConMon/__init__.py +0 -0
  160. WMCore/Services/Service.py +400 -0
  161. WMCore/Services/StompAMQ/__init__.py +0 -0
  162. WMCore/Services/TagCollector/TagCollector.py +155 -0
  163. WMCore/Services/TagCollector/XMLUtils.py +98 -0
  164. WMCore/Services/TagCollector/__init__.py +0 -0
  165. WMCore/Services/UUIDLib.py +13 -0
  166. WMCore/Services/UserFileCache/UserFileCache.py +160 -0
  167. WMCore/Services/UserFileCache/__init__.py +8 -0
  168. WMCore/Services/WMAgent/WMAgent.py +63 -0
  169. WMCore/Services/WMAgent/__init__.py +0 -0
  170. WMCore/Services/WMArchive/CMSSWMetrics.py +526 -0
  171. WMCore/Services/WMArchive/DataMap.py +463 -0
  172. WMCore/Services/WMArchive/WMArchive.py +33 -0
  173. WMCore/Services/WMArchive/__init__.py +0 -0
  174. WMCore/Services/WMBS/WMBS.py +97 -0
  175. WMCore/Services/WMBS/__init__.py +0 -0
  176. WMCore/Services/WMStats/DataStruct/RequestInfoCollection.py +300 -0
  177. WMCore/Services/WMStats/DataStruct/__init__.py +0 -0
  178. WMCore/Services/WMStats/WMStatsPycurl.py +145 -0
  179. WMCore/Services/WMStats/WMStatsReader.py +445 -0
  180. WMCore/Services/WMStats/WMStatsWriter.py +273 -0
  181. WMCore/Services/WMStats/__init__.py +0 -0
  182. WMCore/Services/WMStatsServer/WMStatsServer.py +134 -0
  183. WMCore/Services/WMStatsServer/__init__.py +0 -0
  184. WMCore/Services/WorkQueue/WorkQueue.py +492 -0
  185. WMCore/Services/WorkQueue/__init__.py +0 -0
  186. WMCore/Services/__init__.py +8 -0
  187. WMCore/Services/pycurl_manager.py +574 -0
  188. WMCore/WMBase.py +50 -0
  189. WMCore/WMConnectionBase.py +164 -0
  190. WMCore/WMException.py +183 -0
  191. WMCore/WMExceptions.py +269 -0
  192. WMCore/WMFactory.py +76 -0
  193. WMCore/WMInit.py +377 -0
  194. WMCore/WMLogging.py +104 -0
  195. WMCore/WMSpec/ConfigSectionTree.py +442 -0
  196. WMCore/WMSpec/Persistency.py +135 -0
  197. WMCore/WMSpec/Steps/BuildMaster.py +87 -0
  198. WMCore/WMSpec/Steps/BuildTools.py +201 -0
  199. WMCore/WMSpec/Steps/Builder.py +97 -0
  200. WMCore/WMSpec/Steps/Diagnostic.py +89 -0
  201. WMCore/WMSpec/Steps/Emulator.py +62 -0
  202. WMCore/WMSpec/Steps/ExecuteMaster.py +208 -0
  203. WMCore/WMSpec/Steps/Executor.py +210 -0
  204. WMCore/WMSpec/Steps/StepFactory.py +213 -0
  205. WMCore/WMSpec/Steps/TaskEmulator.py +75 -0
  206. WMCore/WMSpec/Steps/Template.py +204 -0
  207. WMCore/WMSpec/Steps/Templates/AlcaHarvest.py +76 -0
  208. WMCore/WMSpec/Steps/Templates/CMSSW.py +613 -0
  209. WMCore/WMSpec/Steps/Templates/DQMUpload.py +59 -0
  210. WMCore/WMSpec/Steps/Templates/DeleteFiles.py +70 -0
  211. WMCore/WMSpec/Steps/Templates/LogArchive.py +84 -0
  212. WMCore/WMSpec/Steps/Templates/LogCollect.py +105 -0
  213. WMCore/WMSpec/Steps/Templates/StageOut.py +105 -0
  214. WMCore/WMSpec/Steps/Templates/__init__.py +10 -0
  215. WMCore/WMSpec/Steps/WMExecutionFailure.py +21 -0
  216. WMCore/WMSpec/Steps/__init__.py +8 -0
  217. WMCore/WMSpec/Utilities.py +63 -0
  218. WMCore/WMSpec/WMSpecErrors.py +12 -0
  219. WMCore/WMSpec/WMStep.py +347 -0
  220. WMCore/WMSpec/WMTask.py +1997 -0
  221. WMCore/WMSpec/WMWorkload.py +2288 -0
  222. WMCore/WMSpec/WMWorkloadTools.py +382 -0
  223. WMCore/WMSpec/__init__.py +9 -0
  224. WMCore/WorkQueue/DataLocationMapper.py +273 -0
  225. WMCore/WorkQueue/DataStructs/ACDCBlock.py +47 -0
  226. WMCore/WorkQueue/DataStructs/Block.py +48 -0
  227. WMCore/WorkQueue/DataStructs/CouchWorkQueueElement.py +148 -0
  228. WMCore/WorkQueue/DataStructs/WorkQueueElement.py +274 -0
  229. WMCore/WorkQueue/DataStructs/WorkQueueElementResult.py +152 -0
  230. WMCore/WorkQueue/DataStructs/WorkQueueElementsSummary.py +185 -0
  231. WMCore/WorkQueue/DataStructs/__init__.py +0 -0
  232. WMCore/WorkQueue/Policy/End/EndPolicyInterface.py +44 -0
  233. WMCore/WorkQueue/Policy/End/SingleShot.py +22 -0
  234. WMCore/WorkQueue/Policy/End/__init__.py +32 -0
  235. WMCore/WorkQueue/Policy/PolicyInterface.py +17 -0
  236. WMCore/WorkQueue/Policy/Start/Block.py +258 -0
  237. WMCore/WorkQueue/Policy/Start/Dataset.py +180 -0
  238. WMCore/WorkQueue/Policy/Start/MonteCarlo.py +131 -0
  239. WMCore/WorkQueue/Policy/Start/ResubmitBlock.py +171 -0
  240. WMCore/WorkQueue/Policy/Start/StartPolicyInterface.py +316 -0
  241. WMCore/WorkQueue/Policy/Start/__init__.py +34 -0
  242. WMCore/WorkQueue/Policy/__init__.py +57 -0
  243. WMCore/WorkQueue/WMBSHelper.py +772 -0
  244. WMCore/WorkQueue/WorkQueue.py +1237 -0
  245. WMCore/WorkQueue/WorkQueueBackend.py +750 -0
  246. WMCore/WorkQueue/WorkQueueBase.py +39 -0
  247. WMCore/WorkQueue/WorkQueueExceptions.py +44 -0
  248. WMCore/WorkQueue/WorkQueueReqMgrInterface.py +278 -0
  249. WMCore/WorkQueue/WorkQueueUtils.py +130 -0
  250. WMCore/WorkQueue/__init__.py +13 -0
  251. WMCore/Wrappers/JsonWrapper/JSONThunker.py +342 -0
  252. WMCore/Wrappers/JsonWrapper/__init__.py +7 -0
  253. WMCore/Wrappers/__init__.py +6 -0
  254. WMCore/__init__.py +10 -0
  255. wmglobalqueue-2.4.5.1.data/data/bin/wmc-dist-patch +15 -0
  256. wmglobalqueue-2.4.5.1.data/data/bin/wmc-dist-unpatch +8 -0
  257. wmglobalqueue-2.4.5.1.data/data/bin/wmc-httpd +3 -0
  258. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/.couchapprc +1 -0
  259. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/README.md +40 -0
  260. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/index.html +264 -0
  261. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/ElementInfoByWorkflow.js +96 -0
  262. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/StuckElementInfo.js +57 -0
  263. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/WorkloadInfoTable.js +80 -0
  264. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/dataTable.js +70 -0
  265. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/namespace.js +23 -0
  266. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/style/main.css +75 -0
  267. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/couchapp.json +4 -0
  268. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/childQueueFilter.js +13 -0
  269. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/filterDeletedDocs.js +3 -0
  270. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/queueFilter.js +11 -0
  271. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/language +1 -0
  272. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/mustache.js +333 -0
  273. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/validate.js +27 -0
  274. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/workqueue_utils.js +61 -0
  275. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/elementsDetail.js +28 -0
  276. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/filter.js +86 -0
  277. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/stuckElements.js +38 -0
  278. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/workRestrictions.js +153 -0
  279. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/workflowSummary.js +28 -0
  280. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/rewrites.json +73 -0
  281. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/shows/redirect.js +23 -0
  282. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/shows/status.js +40 -0
  283. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/ElementSummaryByWorkflow.html +27 -0
  284. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/StuckElementSummary.html +26 -0
  285. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/TaskStatus.html +23 -0
  286. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/WorkflowSummary.html +27 -0
  287. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/workqueue-common-lib.html +2 -0
  288. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib-remote.html +16 -0
  289. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib.html +18 -0
  290. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/updates/in-place.js +50 -0
  291. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/validate_doc_update.js +8 -0
  292. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.couch.app.js +235 -0
  293. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.pathbinder.js +173 -0
  294. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeData/map.js +8 -0
  295. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeData/reduce.js +2 -0
  296. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeParentData/map.js +8 -0
  297. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeParentData/reduce.js +2 -0
  298. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activePileupData/map.js +8 -0
  299. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activePileupData/reduce.js +2 -0
  300. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/analyticsData/map.js +11 -0
  301. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/analyticsData/reduce.js +1 -0
  302. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/availableByPriority/map.js +6 -0
  303. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/conflicts/map.js +5 -0
  304. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elements/map.js +5 -0
  305. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByData/map.js +8 -0
  306. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByParent/map.js +8 -0
  307. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByParentData/map.js +8 -0
  308. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByPileupData/map.js +8 -0
  309. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByStatus/map.js +8 -0
  310. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsBySubscription/map.js +6 -0
  311. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/map.js +8 -0
  312. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/reduce.js +3 -0
  313. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsDetailByWorkflowAndStatus/map.js +26 -0
  314. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/map.js +10 -0
  315. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/reduce.js +1 -0
  316. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/map.js +6 -0
  317. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/reduce.js +1 -0
  318. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/map.js +6 -0
  319. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/reduce.js +1 -0
  320. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/map.js +6 -0
  321. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/reduce.js +1 -0
  322. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByRequest/map.js +6 -0
  323. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByRequest/reduce.js +1 -0
  324. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatus/map.js +6 -0
  325. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatus/reduce.js +1 -0
  326. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/map.js +6 -0
  327. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/reduce.js +1 -0
  328. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/openRequests/map.js +6 -0
  329. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/recent-items/map.js +5 -0
  330. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/map.js +6 -0
  331. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/reduce.js +1 -0
  332. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/specsByWorkflow/map.js +5 -0
  333. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/stuckElements/map.js +38 -0
  334. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/map.js +12 -0
  335. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/reduce.js +3 -0
  336. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrl/map.js +6 -0
  337. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrl/reduce.js +2 -0
  338. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/map.js +6 -0
  339. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/reduce.js +2 -0
  340. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/workflowSummary/map.js +9 -0
  341. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/workflowSummary/reduce.js +10 -0
  342. wmglobalqueue-2.4.5.1.dist-info/METADATA +26 -0
  343. wmglobalqueue-2.4.5.1.dist-info/RECORD +347 -0
  344. wmglobalqueue-2.4.5.1.dist-info/WHEEL +5 -0
  345. wmglobalqueue-2.4.5.1.dist-info/licenses/LICENSE +202 -0
  346. wmglobalqueue-2.4.5.1.dist-info/licenses/NOTICE +16 -0
  347. wmglobalqueue-2.4.5.1.dist-info/top_level.txt +2 -0
@@ -0,0 +1,29 @@
1
+ from builtins import object
2
+
3
+
4
+ class ConfigDBMapInterface(object):
5
+ """
6
+ Interface for converting the configuration to
7
+ db url string and option dictionary for DBFactory parameters
8
+
9
+ the implementation of this class should create db url string.
10
+ and option for DBFactory creation.
11
+ For details of options, reference WMCore.Database.DBFactory
12
+ """
13
+
14
+ def __init__(self, config):
15
+ self.config = config
16
+
17
+ def getDBUrl(self):
18
+ """
19
+ this should return db string
20
+ i.e. mysql://username@hostname.fnal.gov:3306/TestDB
21
+ """
22
+ raise NotImplementedError("getDBUrl is not implemented")
23
+
24
+ def getOption(self):
25
+ """
26
+ this should return options of dict format
27
+ i.e. {'engine_parameters': {'pool_size': 10}}
28
+ """
29
+ raise NotImplementedError("getOption is not implemented")
@@ -0,0 +1,450 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ This module provides helper functions to obtain and handle CouchDB Replication data:
4
+ - getSchedulerJobDocs get replication status based on scheduler information
5
+ - getReplicatorDocs get replication status based on replicator information
6
+ - compareReplicationStatus compares previous and current statuses
7
+ - formatPrometheusMetrics format status metrics in Prometheus format
8
+ - createAlerts create alerts from given status dict
9
+ - checkStatus perform all checks for couchdb replication
10
+
11
+ Example of using Flask framework to serve prometheus metrics about CouchDB replication
12
+
13
+ import requests
14
+ from flask import Flask, Response
15
+ import threading
16
+ import time
17
+
18
+ app = Flask(__name__)
19
+ status_cache = {}
20
+
21
+ @app.route("/metrics")
22
+ def metrics():
23
+ return Response(formatPrometheusMetrics(status_cache), mimetype="text/plain")
24
+
25
+ def daemonCouchReplicationStatus(interval=30):
26
+ global status_cache
27
+ while True:
28
+ new_status = getSchedulerJobDocs(COUCHDB_URL, USERNAME, PASSWORD)
29
+ status_cache = new_status
30
+ time.sleep(interval)
31
+
32
+ if __name__ == "__main__":
33
+ # Start the background thread to update replication status periodically
34
+ threading.Thread(target=daemonCouchReplicationStatus, daemon=True).start()
35
+ # Run the Flask app
36
+ app.run(host="0.0.0.0", port=8000)
37
+ """
38
+
39
+ import os
40
+ import json
41
+ import requests
42
+ import tempfile
43
+
44
+ # WMCore modules
45
+ from Utils.CertTools import cert, ckey, caBundle
46
+
47
+
48
+ def getSchedulerJobDocs(couchdbUrl):
49
+ """
50
+ Fetch CouchDB replication statuses. The logic is based on /_scheduler/jobs CouchDB end-point
51
+ see https://docs.couchdb.org/en/stable/api/server/common.html#api-server-scheduler-jobs
52
+ :param couchdbUrl: url of couch db
53
+ :return: dictionary of statuses for all found replication documents
54
+ """
55
+ username, password = couchCredentials()
56
+ auth = (username, password) if username and password else None
57
+ try:
58
+ response = requests.get(f"{couchdbUrl}/_scheduler/jobs", auth=auth)
59
+ response.raise_for_status()
60
+ data = response.json()
61
+
62
+ statuses = {}
63
+ for job in data.get('jobs', []):
64
+ doc_id = job.get('doc_id') or job.get('id')
65
+ source = job.get('source')
66
+ target = job.get('target')
67
+ history = job.get('history', [])
68
+ info = job.get('info', {})
69
+
70
+ # Determine current state from latest history item
71
+ state = history[0]['type'] if history else 'unknown'
72
+
73
+ # Detect error if 'crashed' exists in any history entry
74
+ error = None
75
+ for h in history:
76
+ if h.get('type') == 'crashed':
77
+ error = f"Job previous crashed at {h.get('timestamp')} due to {h.get('reason')}"
78
+ break
79
+
80
+ # check info document
81
+ if info and info.get('doc_write_failures', 0) != 0:
82
+ error = f"found failure of replication jobs in {couchdbUrl}/_scheduler/jobs "
83
+ state = "error"
84
+ # try to get more info about the error
85
+ try:
86
+ response = requests.get(f"{couchdbUrl}/_scheduler/docs/_replicator/{doc_id}", auth=auth)
87
+ response.raise_for_status()
88
+ data = response.json()
89
+ error += f" Replicator state for {doc_id}: "
90
+ error += json.dumps(data)
91
+ except:
92
+ pass
93
+
94
+ statuses[doc_id] = {
95
+ 'state': state,
96
+ 'source': source,
97
+ 'target': target,
98
+ 'error': error,
99
+ 'history': history
100
+ }
101
+
102
+ return statuses
103
+ except requests.RequestException as e:
104
+ print(f"Error fetching scheduler jobs: {e}")
105
+ return {}
106
+
107
+
108
+ def getReplicatorDocs(url=None):
109
+ """
110
+ Helper function to get all replicator docs and return summary dictionary
111
+ :param url: url of the couchdb
112
+ :return: replication summary dictionary
113
+ """
114
+ username, password = couchCredentials()
115
+ auth = (username, password) if username and password else None
116
+ if not url:
117
+ url = "http://localhost:5984"
118
+ headers = {"Accept": "application/json"}
119
+
120
+ # Get list of all documents in _replicator
121
+ r = requests.get(f"{url}/_replicator/_all_docs?include_docs=true",
122
+ headers=headers, auth=auth)
123
+
124
+ if r.status_code != 200:
125
+ raise Exception(f"Failed to fetch replication docs: {r.text}")
126
+
127
+ data = r.json()
128
+ result = {}
129
+
130
+ for row in data.get("rows", []):
131
+ doc = row.get("doc", {})
132
+ doc_id = doc.get("_id")
133
+ if doc_id.startswith("_design/"):
134
+ continue # skip design docs
135
+
136
+ summary = {
137
+ "state": doc.get("_replication_state"),
138
+ "source": doc.get("source"),
139
+ "target": doc.get("target"),
140
+ "error": doc.get("_replication_state_reason"),
141
+ "history": []
142
+ }
143
+
144
+ history = doc.get("_replication_history", [])
145
+ for h in history:
146
+ entry = {
147
+ "timestamp": h.get("start_time") or h.get("end_time"),
148
+ "type": h.get("type") or "unknown"
149
+ }
150
+ summary["history"].append(entry)
151
+
152
+ result[doc_id] = summary
153
+
154
+ return result
155
+
156
+
157
+ def compareReplicationStatus(prev, curr):
158
+ """
159
+ Helper function to compare replication status from previous to current state
160
+ :param prev: previous replication status dictionary
161
+ :param curr: current replication status dictionary
162
+ :return: dictionary of changes
163
+ """
164
+ changes = {}
165
+ for key in curr:
166
+ if key not in prev or prev[key] != curr[key]:
167
+ changes[key] = {
168
+ 'old': prev.get(key),
169
+ 'new': curr[key]
170
+ }
171
+ return changes
172
+
173
+
174
+ def formatPrometheusMetrics(statuses):
175
+ """
176
+ Helper function to provide Prometheus metrics from given status dictionary
177
+ :param statuses: replication status dictionary
178
+ :return: prometheus metrics
179
+ """
180
+ states = {'error': -1, 'completed': 0, 'started': 1, 'added': 2, 'waiting': 3, 'triggered': 4, 'failed': 5}
181
+ lines = [
182
+ f'# HELP couchdb_replication_state Replication state: {states}',
183
+ '# TYPE couchdb_replication_state gauge'
184
+ ]
185
+ for key, status in statuses.items():
186
+ label = f'replId="{key}",source="{status["source"]}",target="{status["target"]}"'
187
+ value = 0 # default error/other
188
+ for k, v in states.items():
189
+ if status['state'] == k:
190
+ value = v
191
+ break
192
+ lines.append(f'couchdb_replication_state{{{label}}} {value}')
193
+ return '\n'.join(lines)
194
+
195
+
196
+ def createAlerts(statuses):
197
+ """
198
+ Helper function to check alerts of replication status dictionary
199
+ :param statuses: replication status dictionary
200
+ :return: alerts dictionary
201
+ """
202
+ alerts = {}
203
+ for key, status in statuses.items():
204
+ if status['state'] != 'completed':
205
+ alerts[key] = f"Replication state for {key} is '{status['state']}', error: {status['error']}"
206
+ return alerts
207
+
208
+
209
+ def couchCredentials():
210
+ """
211
+ Select CouchDB credentials from provided secrets file
212
+ :return: tuple of (user, password)
213
+ """
214
+ fname = os.getenv('WMAGENT_SECRETS_LOCATION', '')
215
+ if fname == "":
216
+ raise Exception("No WMAGENT_SECRETS_LOCATION in environment")
217
+ user = ''
218
+ password = ''
219
+ data = ''
220
+ with open(fname, 'r', encoding="utf-8") as istream:
221
+ data = istream.read()
222
+ for item in data.split('\n'):
223
+ if 'COUCH_USER' in item:
224
+ user = item.split('=')[-1]
225
+ if 'COUCH_PASS' in item:
226
+ password = item.split('=')[-1]
227
+ return user, password
228
+
229
+
230
+ def checkStatus(url=None, prevStatus=None, kind="scheduler"):
231
+ """
232
+ Perform check of replication statuses
233
+ :param url: couchdb URL
234
+ :param prevStatus: previous status dictionary
235
+ :param kind: kind of data look-up, e.g. scheduler or replicator
236
+ :return: dictionary of current couchdb replication
237
+
238
+ Here is an example of such dictionary structure:
239
+ {'current_status': currStatus (dictionary),
240
+ 'previous_status': prevStatus (dictionary),
241
+ 'changes': changes (dictionary),
242
+ 'metrics': metrics (string),
243
+ 'alerts': alerts (dictionary)}
244
+
245
+ Then, current and previous status dictionaries have the following form:
246
+ {
247
+ "14843c24643f8960eb159f5912f0f938": {
248
+ "state": "started",
249
+ "source": "https://xxx.cern.ch/couchdb/workqueue/",
250
+ "target": "http://127.0.0.1:5984/workqueue_inbox/",
251
+ "error": "Job previously crashed at 2025-05-05T18:47:11Z due to {changes_reader_died,{timeout,ibrowse_stream_cleanup}}",
252
+ "history": [
253
+ {
254
+ "timestamp": "2025-05-05T18:47:11Z",
255
+ "type": "started"
256
+ },
257
+ ...
258
+ ]
259
+ },
260
+ "14843c24643f8960eb159f5912f0e51e": {
261
+ "state": "started",
262
+ "source": "http://127.0.0.1:5984/wmagent_summary/",
263
+ "target": "https://xxx.cern.ch/couchdb/wmstats/",
264
+ "error": null,
265
+ "history": [
266
+ {
267
+ "timestamp": "2025-04-09T11:19:36Z",
268
+ "type": "started"
269
+ },
270
+ {
271
+ "timestamp": "2025-04-09T11:19:36Z",
272
+ "type": "added"
273
+ }
274
+ ]
275
+ },
276
+ ...
277
+ }
278
+ """
279
+ if not prevStatus:
280
+ prevStatus = {}
281
+ if not url:
282
+ url = "http://localhost:5984"
283
+
284
+ # first let's get statuses of documents
285
+ if kind == "scheduler":
286
+ currStatus = getSchedulerJobDocs(url)
287
+ elif kind == "replicator":
288
+ currStatus = getReplicatorDocs(url)
289
+ else:
290
+ raise Exception("Unsupported kind of documents '{kind}', should be either scheduler or replicator")
291
+
292
+ # now we can find out changes from previous statuses
293
+ changes = compareReplicationStatus(prevStatus, currStatus)
294
+
295
+ # construct prometheus metrics with current statuses
296
+ metrics = formatPrometheusMetrics(currStatus)
297
+
298
+ # construct alerts with current statuses
299
+ alerts = createAlerts(currStatus)
300
+
301
+ # build final dictionary to return upstream
302
+ sdict = {'current_status': currStatus,
303
+ 'previous_status': prevStatus,
304
+ 'changes': changes,
305
+ 'metrics': metrics,
306
+ 'alerts': alerts}
307
+ return sdict
308
+
309
+
310
+ def getDocCount(url, auth, certTuple, caCert):
311
+ """
312
+ helper function to get document counts
313
+ :param url: url of the couchdb
314
+ :param auth: couchdb authentication credentials tuple
315
+ :param caCert: ca bundle file name
316
+ :return: document count
317
+ """
318
+ resp = requests.get(url, auth=auth, cert=certTuple, verify=caCert or True)
319
+ resp.raise_for_status()
320
+ return resp.json().get('doc_count', -1)
321
+
322
+
323
+ def getReplicationState(url, auth, certTuple, caCert):
324
+ """
325
+ helper function to get replication state from given couchdb url
326
+ :param url: url of the couchdb
327
+ :param auth: couchdb authentication credentials tuple
328
+ :param caCert: ca bundle file name
329
+ :return: tuple of replication state and its time
330
+ """
331
+ resp = requests.get(url, auth=auth, cert=certTuple, verify=caCert or True)
332
+ resp.raise_for_status()
333
+ doc = resp.json()
334
+ return doc.get('_replication_state'), doc.get('_replication_state_time')
335
+
336
+
337
+ def compareCouchInstances(sourceUrl, targetUrl, replUrl):
338
+ """
339
+ Compare the number of documents between source and destination CouchDB databases.
340
+ Monitor replication if the counts differ but replication status is OK.
341
+
342
+ Parameters:
343
+ :param sourceUrl: str, e.g. http://localhost:5984/source_db
344
+ :param targetUrl: str, e.g. http://localhost:5984/dest_db
345
+ :param replUrl: str, e.g. http://localhost:5984/_replicator/<replId>
346
+ """
347
+ user, password = couchCredentials()
348
+ auth = (user, password)
349
+ sdict = {}
350
+ userCert = cert() if cert() else ''
351
+ userCkey = ckey() if ckey() else ''
352
+ if userCkey == '' or userCert == '':
353
+ return sdict
354
+ certTuple = (userCert, userCkey)
355
+ with tempfile.NamedTemporaryFile(mode='w+', suffix=".pem", delete=True) as tfile:
356
+ capath = os.environ.get("X509_CERT_DIR", '/etc/grid-security/certificates')
357
+ cacerts = caBundle(capath)
358
+ tfile.write(cacerts)
359
+ tfile.flush()
360
+
361
+ sourceCount = getDocCount(sourceUrl, auth, certTuple, tfile.name)
362
+ targetCount = getDocCount(targetUrl, auth, certTuple, tfile.name)
363
+ state, stateTime = getReplicationState(replUrl, auth, certTuple, tfile.name)
364
+
365
+ sdict = {
366
+ "source": sourceUrl,
367
+ "target": targetUrl,
368
+ "source_count": sourceCount,
369
+ "target_count": targetCount,
370
+ "state": state,
371
+ "state_timestamp": stateTime
372
+ }
373
+ return sdict
374
+
375
+
376
+ def exampleReplicationStatus(sourceUrl=None):
377
+ """
378
+ Example function to test replication status either based on scheduler or replicator info
379
+ This function should run on a node with local CouchDB access as all of its logic
380
+ relies on using localhost:5984 URL
381
+ """
382
+
383
+ try:
384
+ print(f"checking {sourceUrl}")
385
+
386
+ # let's first test scheduler info
387
+ sdict = checkStatus(url=sourceUrl, kind="scheduler")
388
+ print('--- status based on scheduler info ---')
389
+ print(sdict['current_status'])
390
+ print('--- metrics ---')
391
+ print(sdict['metrics'])
392
+ if sdict.get('alerts', None):
393
+ print('--- alerts ---')
394
+ for k, msg in sdict['alerts'].items():
395
+ print(f"{k}: {msg}")
396
+
397
+ print()
398
+
399
+ # now let's test replicator info
400
+ rdict = checkStatus(url=sourceUrl, kind="replicator")
401
+ print('--- status based on replicator info ---')
402
+ print(rdict['current_status'])
403
+ print('--- metrics ---')
404
+ print(rdict['metrics'])
405
+ if rdict.get('alerts', None):
406
+ print('--- alerts ---')
407
+ for k, msg in rdict['alerts'].items():
408
+ print(f"{k}: {msg}")
409
+
410
+ except Exception as exp:
411
+ print(str(exp))
412
+
413
+
414
+ def exampleIndividualDocument(sourceUrl, targetUrl, replUrl):
415
+ """
416
+ Example function how to test check status of particular replication document
417
+ This function should run through CMSWEB frontend URLs as we need to compare
418
+ documents in both source and target CouchDB instances
419
+ :param sourceUrl: source couchdb URL, e.g. https://xxx.cern.ch/couchdb/test_db
420
+ :param targetUrl: target couchdb URL, e.g. https://xxx.cern.ch/couchdb/test_db
421
+ :param replUrl: replication URL, e.g. https://xxx.cern.ch/couchdb/test_db/_replicator/bla
422
+ """
423
+ try:
424
+ result = compareCouchInstances(sourceUrl, targetUrl, replUrl)
425
+ print('--- compare CouchDB Instances ---')
426
+ print('source: ', sourceUrl)
427
+ print('target: ', targetUrl)
428
+ print(result)
429
+ except:
430
+ pass
431
+
432
+
433
+ def test():
434
+ """
435
+ test functions
436
+ """
437
+ import sys
438
+ if len(sys.argv) > 1:
439
+ sourceUrl = sys.argv[1]
440
+ exampleReplicationStatus(sourceUrl)
441
+ else:
442
+ print("Cannot run tests, please provide at least CouchDB source URL, or <srcUrl> <targetUrl> <replicationId>")
443
+ if len(sys.argv) == 4:
444
+ sourceUrl = sys.argv[1]
445
+ targetUrl = sys.argv[2]
446
+ replUrl = sys.argv[3]
447
+ exampleIndividualDocument(sourceUrl, targetUrl, replUrl)
448
+
449
+ if __name__ == '__main__':
450
+ test()
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env python
2
+ # encoding: utf-8
3
+ """
4
+ CouchUtils.py
5
+
6
+ Created by Dave Evans on 2010-03-11.
7
+ Copyright (c) 2010 Fermilab. All rights reserved.
8
+ """
9
+ from __future__ import print_function
10
+
11
+ from future import standard_library
12
+ standard_library.install_aliases()
13
+
14
+ from http.client import HTTPException
15
+
16
+ import functools
17
+
18
+ import WMCore.Database.CMSCouch as CMSCouch
19
+
20
+
21
+ class CouchConnectionError(Exception):
22
+ """docstring for CouchConnectionError"""
23
+ def __init__(self, arg):
24
+ super(CouchConnectionError, self).__init__(arg)
25
+
26
+
27
+
28
+
29
+ def initialiseCouch(objectRef):
30
+ if objectRef.couchdb != None:
31
+ return
32
+ if objectRef.url == None:
33
+ msg = "url for couch service not provided"
34
+ raise CouchConnectionError(msg)
35
+ if objectRef.database == None:
36
+ msg = "database name for couch service not provided"
37
+ raise CouchConnectionError(msg)
38
+ try:
39
+ objectRef.server = CMSCouch.CouchServer(objectRef.url)
40
+ objectRef.couchdb = objectRef.server.connectDatabase(objectRef.database)
41
+ except HTTPException as e:
42
+ msg = "%s with status: %s, reason: %s and result: %s" % (repr(e),
43
+ getattr(e, 'status', ""),
44
+ getattr(e, 'reason', ""),
45
+ getattr(e, 'result', ""))
46
+ raise CouchConnectionError(msg)
47
+ except Exception as e:
48
+ msg = "Exception instantiating couch services for :\n"
49
+ msg += " url = %s\n database = %s\n" % (objectRef.url, objectRef.database)
50
+ msg += " Exception: %s" % str(e)
51
+ print(msg)
52
+ raise CouchConnectionError(msg)
53
+
54
+ def connectToCouch(funcRef):
55
+ """
56
+ _connectToCouch_
57
+
58
+ Decorator method to connect the function's class object to couch
59
+ """
60
+ @functools.wraps(funcRef)
61
+ def wrapper(x, *args, **opts):
62
+ initialiseCouch(x)
63
+ return funcRef(x, *args, **opts)
64
+ return wrapper
65
+
66
+ def requireOwner(func):
67
+ """
68
+ _requireOwner_
69
+
70
+ Decorator to ensure that the owner attribute of a couch ACDC object is not None
71
+ """
72
+
73
+ def wrapper(self, *args, **opts):
74
+ if self.owner == None:
75
+ msg = "Owner not provided for Collection"
76
+ raise RuntimeError(msg)
77
+ return func(self, *args, **opts)
78
+ return wrapper
79
+
80
+ def requireCollection(func):
81
+ """
82
+ _requireCollection_
83
+
84
+ Decorator to ensure that the collection attribute of a couch ACDC object is not None
85
+ """
86
+
87
+ def wrapper(self, *args, **opts):
88
+ if self.collection == None:
89
+ msg = "Collection not provided for Collection"
90
+ raise RuntimeError(msg)
91
+ return func(self, *args, **opts)
92
+ return wrapper
93
+
94
+ def requireFilesetName(func):
95
+ """
96
+ _requireFilesetName_
97
+
98
+ Decorator to require that a fileset has a name that is not None
99
+
100
+ """
101
+ def wrapper(self, *args, **opts):
102
+ if not 'name' in self or self['name'] == None:
103
+ raise RuntimeError("Filesets must be named")
104
+ return func(self, *args, **opts)
105
+ return wrapper
106
+
107
+ def requireCollectionName(func):
108
+ """
109
+ _requireCollectionName_
110
+
111
+ Decorator to require that a collection has a name that is not None
112
+
113
+ """
114
+ def wrapper(self, *args, **opts):
115
+ if not 'name' in self or self['name'] == None:
116
+ raise RuntimeError("Filesets must be named")
117
+ return func(self, *args, **opts)
118
+ return wrapper