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
WMCore/Lexicon.py ADDED
@@ -0,0 +1,836 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ _Lexicon_
4
+
5
+ A set of regular expressions and other tests that we can use to validate input
6
+ to other classes. If a test fails an AssertionError should be raised, and
7
+ handled appropriately by the client methods, on success returns True.
8
+ """
9
+ from __future__ import print_function, division
10
+
11
+ from future import standard_library
12
+ standard_library.install_aliases()
13
+ from builtins import str, bytes
14
+ from future.utils import viewvalues, viewkeys
15
+
16
+ import io
17
+ import re
18
+ import json
19
+
20
+ from urllib.parse import urlparse, urlunparse
21
+
22
+ from WMCore.WMException import WMException, WMEXCEPTION_START_STR, WMEXCEPTION_END_STR
23
+
24
+ # restriction enforced by DBS. for different types blocks.
25
+ # It could have a strict restriction
26
+ # i.e production should end with v[number]
27
+ PRIMARY_DS = {'re': '^[a-zA-Z][a-zA-Z0-9\-_]*$', 'maxLength': 99}
28
+ PROCESSED_DS = {'re': '[a-zA-Z0-9\.\-_]+', 'maxLength': 199}
29
+ TIER = {'re': '[A-Z0-9\-_]+', 'maxLength': 99}
30
+ BLOCK_STR = {'re': '#[a-zA-Z0-9\.\-_]+', 'maxLength': 100}
31
+
32
+ lfnParts = {
33
+ 'era': '([a-zA-Z0-9\-_]+)',
34
+ 'primDS': '([a-zA-Z][a-zA-Z0-9\-_]*)',
35
+ 'tier': '(%(re)s)' % TIER,
36
+ 'version': '([a-zA-Z0-9\-_]+)',
37
+ 'procDS': '([a-zA-Z0-9\-_]+)', # Processed dataset = Processing string + Processing version
38
+ 'counter': '([0-9]+)',
39
+ 'root': '([a-zA-Z0-9\-_]+).root',
40
+ 'hnName': '([a-zA-Z0-9\.]+)',
41
+ 'subdir': '([a-zA-Z0-9\-_]+)',
42
+ 'file': '([a-zA-Z0-9\-\._]+)',
43
+ 'workflow': '([a-zA-Z0-9\-_]+)',
44
+ 'physics_group': '([a-zA-Z0-9\-_]+)'
45
+ }
46
+
47
+ userProcDSParts = {
48
+ 'groupuser': '([a-zA-Z0-9\.\-_])+',
49
+ 'publishdataname': '([a-zA-Z0-9\-_])+',
50
+ 'psethash': '([a-f0-9]){32}'
51
+ }
52
+
53
+ STORE_RESULTS_LFN = '/store/results/%(physics_group)s/%(era)s/%(primDS)s/%(tier)s/%(procDS)s' % lfnParts
54
+
55
+ # condor log filtering lexicons
56
+ WMEXCEPTION_FILTER = "(?P<WMException>\%s(?!<@).*?\%s)" % (WMEXCEPTION_START_STR, WMEXCEPTION_END_STR)
57
+ WMEXCEPTION_FILTER += "|(?P<ERROR>(ERROR:root:.*?This is a CRITICAL error))"
58
+ WMEXCEPTION_REGEXP = re.compile(r"%s" % WMEXCEPTION_FILTER, re.DOTALL)
59
+
60
+ CONDOR_LOG_REASON_FILTER = '<a n="Reason"><s>(?P<Reason>(?!</s></a>).*?)</s></a>'
61
+ CONDOR_LOG_SITE_FILTER = '<a n="MachineAttrGLIDEIN_CMSSite0"><s>(?P<Site>(?!</s></a>).*?)</s></a>'
62
+
63
+ CONDOR_LOG_FILTER_REGEXP = re.compile(r"%s|%s" % (CONDOR_LOG_REASON_FILTER, CONDOR_LOG_SITE_FILTER),
64
+ re.DOTALL)
65
+
66
+
67
+ def DBSUser(candidate):
68
+ """
69
+ create_by and last_modified_by in DBS are in several formats. The major ones are:
70
+ 1. DN that was mostly used in DBS2: example /DC=org/DC=doegrids/OU=People/CN=Lothar A.T. Bauerdick 301799;
71
+ 2. CERN HN account name that used in DBS3/CMSWEB if the HN is assocated with DN: example giffels ;
72
+ 3. username with host name: example cmsprod@vocms39.cern.ch;
73
+ """
74
+ if candidate == '' or not candidate:
75
+ return candidate
76
+ r1 = r'^/[a-zA-Z][a-zA-Z0-9/\=\s()\']*\=[a-zA-Z0-9/\=\.\-_/#:\s\']*$'
77
+ r2 = r'^[a-zA-Z0-9/][a-zA-Z0-9/\.\-_\']*$'
78
+ r3 = r'^[a-zA-Z0-9/][a-zA-Z0-9/\.\-_]*@[a-zA-Z0-9/][a-zA-Z0-9/\.\-_]*$'
79
+
80
+ errorMsg = "DBSUser candidate: %s doesn't match any of the following regular expressions:\n" % candidate
81
+ try:
82
+ return check(r1, candidate)
83
+ except AssertionError:
84
+ errorMsg += " %s\n" % r1
85
+
86
+ try:
87
+ return check(r2, candidate)
88
+ except AssertionError:
89
+ errorMsg += " %s\n" % r2
90
+
91
+ try:
92
+ return check(r3, candidate)
93
+ except AssertionError:
94
+ errorMsg += " %s\n" % r3
95
+ raise AssertionError(errorMsg)
96
+
97
+
98
+ def searchblock(candidate):
99
+ """
100
+ A block name with a * wildcard one or more times in it.
101
+ """
102
+ regexp = r"^/(\*|[a-zA-Z\*][a-zA-Z0-9_\*]{0,100})(/(\*|[a-zA-Z0-9_\.\-\*]{1,199})){0,1}(/(\*|[A-Z0-9\-\*]{1,99})(#(\*|[a-zA-Z0-9\.\-_\*]){0,100}){0,1}){0,1}$"
103
+ return check(regexp, candidate)
104
+
105
+
106
+ SEARCHDATASET_RE = r'^/(\*|[a-zA-Z\*][a-zA-Z0-9_\*\-]{0,100})(/(\*|[a-zA-Z0-9_\.\-\*]{1,199})){0,1}(/(\*|[A-Z0-9\-\*]{1,99})){0,1}$'
107
+
108
+
109
+ def searchdataset(candidate):
110
+ """
111
+ A dataset name with a * wildcard one or more times in it. Only the first '/' is mandatory to use.
112
+ """
113
+ return check(SEARCHDATASET_RE, candidate)
114
+
115
+
116
+ def searchstr(candidate):
117
+ """
118
+ Used to check a DBS input that searches for names in dbs. Note block name, dataset name, file name have their own
119
+ searching string.
120
+ No white space found in names in DBS production and allowed to elimate input like "Drop table table1".
121
+ letters, numbers, periods, dashes, underscores
122
+
123
+ """
124
+ if candidate == '':
125
+ return candidate
126
+ return check(r'^[a-zA-Z0-9/%*][a-zA-Z0-9/\.\-_%*/#]*$', candidate)
127
+
128
+
129
+ def namestr(candidate):
130
+ """
131
+ Any input used in DBS and not defined here should pass namestr check.
132
+ No white space found in names in DBS production and allowed to elimate input like "Drop table table1".
133
+ letters, numbers, periods, dashes, underscores,#,/
134
+
135
+ """
136
+ if candidate == '' or not candidate:
137
+ return candidate
138
+ return check(r'^[a-zA-Z0-9/][a-zA-Z0-9/\.\-_/#]*$', candidate)
139
+
140
+
141
+ def sitetier(candidate):
142
+ return check("^T[0-3]", candidate)
143
+
144
+
145
+ def jobrange(candidate):
146
+ """ Specifies a numbers/range of jobs separated by a comma.
147
+ A range is composed by two numbers separated my minus
148
+ For example valid candidates are either 1 or 1,2 or 3-6,5,7-8
149
+ It is like when you specifies which pages to print in Word
150
+ """
151
+ return check("^\d+(-\d+)?(,\d+(-\d+)?)*$", candidate)
152
+
153
+
154
+ def cmsname(candidate):
155
+ """
156
+ Candidate must pass the CMS name pattern. Thus:
157
+ * good candidates: T2_UK_SGrid or T2_UK_SGrid_Bristol
158
+ * bad candidates: T2, T2_UK
159
+ """
160
+ candidate = candidate.rstrip('_')
161
+ return check("^T[0-3]_[A-Z]{2}((_[A-Za-z0-9]+)+)$", candidate)
162
+
163
+
164
+ def countrycode(candidate):
165
+ # TODO: do properly with a look up table
166
+ return check("^[A-Z]{2}$", candidate)
167
+
168
+
169
+ def _blockStructCheck(candidate):
170
+ """
171
+ Basic block structure check
172
+ /primary/process/tier#uuid
173
+ """
174
+ assert candidate.count('/') == 3, "need to have / between the 3 parts which construct block name"
175
+ parts = candidate.split('/')
176
+ assert parts[3].count('#') == 1, "need to have # in the last parts of block"
177
+ # should be empty string for the first part
178
+ check(r"", parts[0])
179
+ return parts
180
+
181
+
182
+ def block(candidate):
183
+ """assert if not a valid block name"""
184
+
185
+ parts = _blockStructCheck(candidate)
186
+
187
+ primDSCheck = check(r"%s" % PRIMARY_DS['re'], parts[1], PRIMARY_DS['maxLength'])
188
+ procDSCheck = check(r"%s" % PROCESSED_DS['re'], parts[2], PROCESSED_DS['maxLength'])
189
+ lastParts = parts[3].split("#")
190
+ tierCheck = check(r"%s" % TIER['re'], lastParts[0], TIER['maxLength'])
191
+ blockCheck = check(r"%s" % BLOCK_STR['re'], "#%s" % lastParts[1], BLOCK_STR['maxLength'])
192
+ return (primDSCheck and procDSCheck and tierCheck and blockCheck)
193
+
194
+
195
+ def identifier(candidate):
196
+ """ letters, numbers, whitespace, periods, dashes, underscores """
197
+ return check(r'[a-zA-Z0-9\s\.\-_]{1,100}$', candidate)
198
+
199
+
200
+ def globalTag(candidate):
201
+ """ Identifier plus colons """
202
+ return check(r'[a-zA-Z0-9\s\.\-_:]{1,100}$', candidate)
203
+
204
+
205
+ DATASET_RE = r'^/[a-zA-Z0-9\-_]{1,99}/[a-zA-Z0-9\.\-_]{1,199}/[A-Z0-9\-]{1,99}$'
206
+
207
+
208
+ def dataset(candidate):
209
+ """ A slash followed by an identifier,x3 """
210
+ return check(DATASET_RE, candidate)
211
+
212
+
213
+ PROCDATASET_RE = r'[a-zA-Z][a-zA-Z0-9_]*(\-[a-zA-Z0-9_]+){0,2}-v[0-9]*$'
214
+
215
+
216
+ def procdataset(candidate):
217
+ """
218
+ Check for processed dataset name.
219
+ letters, numbers, dashes, underscores.
220
+ """
221
+ if not candidate or candidate.startswith('None'):
222
+ raise AssertionError("ProcDataset cannot be empty or start with None.")
223
+
224
+ commonCheck = check(r"%s" % PROCESSED_DS['re'], candidate, PROCESSED_DS['maxLength'])
225
+ prodCheck = check(PROCDATASET_RE, candidate)
226
+ return (commonCheck and prodCheck)
227
+
228
+
229
+ def publishdatasetname(candidate):
230
+ if candidate == '' or not candidate:
231
+ return candidate
232
+ return check(r'%(publishdataname)s$' % userProcDSParts, candidate, 100)
233
+
234
+
235
+ USERPROCDATASET_RE = r'%(groupuser)s-%(publishdataname)s-%(psethash)s$' % userProcDSParts
236
+
237
+
238
+ def userprocdataset(candidate):
239
+ """
240
+ Check for processed dataset name of users.
241
+ letters, numbers, dashes, underscores.
242
+ """
243
+ if candidate == '' or not candidate:
244
+ return candidate
245
+
246
+ commonCheck = check(r"%s" % PROCESSED_DS['re'], candidate, PROCESSED_DS['maxLength'])
247
+ anlaysisCheck = check(USERPROCDATASET_RE, candidate)
248
+ return (commonCheck and anlaysisCheck)
249
+
250
+
251
+ def physicsgroup(candidate):
252
+ """
253
+ Check for Physics Group string which is added to StoreResults
254
+ merged LFN base. Up to 30 letters, numbers, dashes, underscores.
255
+ """
256
+ return check(r'%(physics_group)s$' % lfnParts, candidate, 30)
257
+
258
+
259
+ def procversion(candidate):
260
+ """ Integers """
261
+ if isinstance(candidate, dict):
262
+ for candi in viewvalues(candidate):
263
+ check(r'^[0-9]+$', str(candi))
264
+ return True
265
+ else:
266
+ return check(r'^[0-9]+$', str(candidate))
267
+
268
+
269
+ def procstring(candidate):
270
+ """ Identifier """
271
+ if not candidate:
272
+ raise AssertionError("ProcStr cannot be empty or None.")
273
+ if isinstance(candidate, dict):
274
+ for candi in viewvalues(candidate):
275
+ check(r'[a-zA-Z0-9_]{1,100}$', candi)
276
+ return True
277
+ else:
278
+ return check(r'[a-zA-Z0-9_]{1,100}$', candidate)
279
+
280
+
281
+ def procstringT0(candidate):
282
+ """
283
+ ProcessingString validation function for T0 specs
284
+ """
285
+ if isinstance(candidate, dict):
286
+ for candi in viewvalues(candidate):
287
+ check(r'^$|[a-zA-Z0-9_]{1,100}$', candi)
288
+ return True
289
+ else:
290
+ return check(r'^$|[a-zA-Z0-9_]{1,100}$', candidate)
291
+
292
+
293
+ def acqname(candidate):
294
+ """
295
+ Check for acquisition name.
296
+ letters, numbers, underscores.
297
+ """
298
+ if not candidate:
299
+ raise AssertionError("AcqEra cannot be empty or None.")
300
+ if isinstance(candidate, dict):
301
+ for candi in viewvalues(candidate):
302
+ check(r'[a-zA-Z][a-zA-Z0-9_]*$', candi)
303
+ return True
304
+ else:
305
+ return check(r'[a-zA-Z][a-zA-Z0-9_]*$', candidate)
306
+
307
+
308
+ def campaign(candidate):
309
+ """
310
+ Check for Campaign name.
311
+ letters, numbers, underscores and dashes are allowed, up to 60 chars.
312
+ """
313
+ if not candidate:
314
+ return True
315
+ return check(r'^[a-zA-Z0-9-_]{1,80}$', candidate)
316
+
317
+
318
+ def primdataset(candidate):
319
+ """
320
+ Check for primary dataset name.
321
+ letters, numbers, dashes, underscores.
322
+ """
323
+ if candidate == '' or not candidate:
324
+ return candidate
325
+ return check(r"%s" % PRIMARY_DS['re'], candidate, PRIMARY_DS['maxLength'])
326
+
327
+
328
+ TASK_STEP_NAME = {'re': '^[a-zA-Z][a-zA-Z0-9\-_]*$', 'maxLength': 50}
329
+ def taskStepName(candidate):
330
+ """
331
+ Validate the TaskName and/or StepName field.
332
+ Letters, numbers, dashes and underscores are allowed.
333
+ """
334
+ return check(r"%s" % TASK_STEP_NAME['re'], candidate, TASK_STEP_NAME['maxLength'])
335
+
336
+ def hnName(candidate):
337
+ """
338
+ Use lfn parts definitions to validate a simple HN name
339
+ """
340
+
341
+ validName = '^%(hnName)s$' % lfnParts
342
+ return check(validName, candidate)
343
+
344
+
345
+ def lfn(candidate):
346
+ """
347
+ Should be of the following form:
348
+ /store/data/acquisition_era/primary-dataset/data_tier/processing_version/lfn_counter/filename.root
349
+ See https://twiki.cern.ch/twiki/bin/viewauth/CMS/DMWMPG_Namespace for details
350
+
351
+ NOTE:Because of the way we do lustre, we have to have two separate checks for this:
352
+ /store/data
353
+ /store/data/lustre
354
+
355
+ Add for LHE files: /data/lhe/...
356
+ """
357
+ regexp1 = '/([a-z]+)/([a-z0-9]+)/(%(era)s)/([a-zA-Z0-9\-_]+)/([A-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)((/[0-9]+){3}){0,1}/([0-9]+)/([a-zA-Z0-9\-_]+).root' % lfnParts
358
+ regexp2 = '/([a-z]+)/([a-z0-9]+)/([a-z0-9]+)/([a-zA-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)/([A-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)((/[0-9]+){3}){0,1}/([0-9]+)/([a-zA-Z0-9\-_]+).root'
359
+ regexp3 = '/store/(temp/)*(user|group)/(%(hnName)s|%(physics_group)s)/%(primDS)s/%(procDS)s/%(version)s/%(counter)s/%(root)s' % lfnParts
360
+ regexp4 = '/store/(temp/)*(user|group)/(%(hnName)s|%(physics_group)s)/%(primDS)s/(%(subdir)s/)+%(root)s' % lfnParts
361
+
362
+ oldStyleTier0LFN = '/store/data/%(era)s/%(primDS)s/%(tier)s/%(version)s/%(counter)s/%(counter)s/%(counter)s/%(root)s' % lfnParts
363
+ tier0LFN = '/store/(backfill/[0-9]/){0,1}(t0temp/|unmerged/){0,1}(data|express|hidata)/%(era)s/%(primDS)s/%(tier)s/%(version)s/%(counter)s/%(counter)s/%(counter)s(/%(counter)s)?/%(root)s' % lfnParts
364
+
365
+ storeMcLFN = '/store/mc/(%(era)s)/([a-zA-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)(/([a-zA-Z0-9\-_]+))*/([a-zA-Z0-9\-_]+).root' % lfnParts
366
+
367
+ storeResults2LFN = '/store/results/%(physics_group)s/%(primDS)s/%(procDS)s/%(primDS)s/%(tier)s/%(procDS)s/%(counter)s/%(root)s' % lfnParts
368
+
369
+ storeResultRootPart = '%(counter)s/%(root)s' % lfnParts
370
+ storeResultsLFN = "%s/%s" % (STORE_RESULTS_LFN, storeResultRootPart)
371
+
372
+ lheLFN1 = '/store/lhe/([0-9]+)/([a-zA-Z0-9\-_]+).lhe(.xz){0,1}'
373
+ # This is for future lhe LFN structure. Need to be tested.
374
+ lheLFN2 = '/store/lhe/%(era)s/%(primDS)s/([0-9]+)/([a-zA-Z0-9\-_]+).lhe(.xz){0,1}' % lfnParts
375
+
376
+ errorMsg = "LFN candidate: %s doesn't match any of the following regular expressions:\n" % candidate
377
+
378
+ try:
379
+ return check(regexp1, candidate)
380
+ except AssertionError:
381
+ errorMsg += " %s\n" % regexp1
382
+
383
+ try:
384
+ return check(regexp2, candidate)
385
+ except AssertionError:
386
+ errorMsg += " %s\n" % regexp2
387
+
388
+ try:
389
+ return check(regexp3, candidate)
390
+ except AssertionError:
391
+ errorMsg += " %s\n" % regexp3
392
+
393
+ try:
394
+ return check(regexp4, candidate)
395
+ except AssertionError:
396
+ errorMsg += " %s\n" % regexp4
397
+
398
+ try:
399
+ return check(tier0LFN, candidate)
400
+ except AssertionError:
401
+ errorMsg += " %s\n" % tier0LFN
402
+
403
+ try:
404
+ return check(oldStyleTier0LFN, candidate)
405
+ except AssertionError:
406
+ errorMsg += " %s\n" % oldStyleTier0LFN
407
+
408
+ try:
409
+ return check(storeMcLFN, candidate)
410
+ except AssertionError:
411
+ errorMsg += " %s\n" % storeMcLFN
412
+
413
+ try:
414
+ return check(lheLFN1, candidate)
415
+ except AssertionError:
416
+ errorMsg += " %s\n" % lheLFN1
417
+
418
+ try:
419
+ return check(lheLFN2, candidate)
420
+ except AssertionError:
421
+ errorMsg += " %s\n" % lheLFN2
422
+
423
+ try:
424
+ return check(storeResults2LFN, candidate)
425
+ except AssertionError:
426
+ errorMsg += " %s\n" % storeResults2LFN
427
+
428
+ try:
429
+ return check(storeResultsLFN, candidate)
430
+ except AssertionError:
431
+ errorMsg += " %s\n" % storeResultsLFN
432
+ raise AssertionError(errorMsg)
433
+
434
+
435
+ def lfnBase(candidate):
436
+ """
437
+ As lfn above, but for doing the lfnBase
438
+ i.e., for use in spec generation and parsing
439
+ """
440
+ regexp1 = '/([a-z]+)/([a-z0-9]+)/([a-zA-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)/([A-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)'
441
+ regexp2 = '/([a-z]+)/([a-z0-9]+)/([a-z0-9]+)/([a-zA-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)/([A-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)((/[0-9]+){3}){0,1}'
442
+ regexp3 = '/(store)/(temp/)*(user|group)/(%(hnName)s|%(physics_group)s)/%(primDS)s/%(procDS)s/%(version)s' % lfnParts
443
+
444
+ tier0LFN = '/store/(backfill/[0-9]/){0,1}(t0temp/|unmerged/){0,1}(data|express|hidata)/%(era)s/%(primDS)s/%(tier)s/%(version)s/%(counter)s/%(counter)s/%(counter)s' % lfnParts
445
+
446
+ errorMsg = "LFN candidate: %s doesn't match any of the following regular expressions:\n" % candidate
447
+
448
+ try:
449
+ return check(regexp1, candidate)
450
+ except AssertionError:
451
+ errorMsg += " %s\n" % regexp1
452
+
453
+ try:
454
+ return check(regexp2, candidate)
455
+ except AssertionError:
456
+ errorMsg += " %s\n" % regexp2
457
+
458
+ try:
459
+ return check(regexp3, candidate)
460
+ except AssertionError:
461
+ errorMsg += " %s\n" % regexp3
462
+
463
+ try:
464
+ return check(tier0LFN, candidate)
465
+ except AssertionError:
466
+ errorMsg += " %s\n" % tier0LFN
467
+
468
+ try:
469
+ return check(STORE_RESULTS_LFN, candidate)
470
+ except AssertionError:
471
+ errorMsg += " %s\n" % STORE_RESULTS_LFN
472
+ raise AssertionError(errorMsg)
473
+
474
+
475
+ def userLfn(candidate):
476
+ """
477
+ Check LFNs in /store/{temp}/user that are not EDM data
478
+ """
479
+ regexp = '/store/(temp/)*(user|group)/(%(hnName)s|%(physics_group)s)/%(subdir)s/%(workflow)s/%(subdir)s/%(file)s' % lfnParts
480
+ return check(regexp, candidate)
481
+
482
+
483
+ def userLfnBase(candidate):
484
+ """
485
+ As above but for the base part of the file
486
+ """
487
+ regexp = '/store/(temp/)*(user|group)/(%(hnName)s|%(physics_group)s)/%(subdir)s/%(workflow)s/%(subdir)s' % lfnParts
488
+ return check(regexp, candidate)
489
+
490
+
491
+ def cmsswversion(candidate):
492
+ return check('CMSSW(_\d+){3}(_[a-zA-Z0-9_]+)?$', candidate)
493
+
494
+
495
+ def couchurl(candidate):
496
+ return check('https?://(([a-zA-Z0-9:@\.\-_]){0,100})([a-z0-9\.]+)(:\d+|/couchdb)', candidate)
497
+
498
+
499
+ def requestName(candidate):
500
+ return check(r'[a-zA-Z0-9\.\-_]{1,150}$', candidate)
501
+
502
+
503
+ def validateUrl(candidate):
504
+ """
505
+ Basic input validation for http(s) urls
506
+ """
507
+ # regex taken from django https://github.com/django/django/blob/master/django/core/validators.py#L47
508
+ # Copyright (c) Django Software Foundation and individual contributors
509
+ protocol = r"^https?://" # http:// or https://
510
+ domain = r'?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}\.?'
511
+ localhost = r'localhost'
512
+ ipv4 = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
513
+ ipv6 = r'\[?[a-fA-F0-9]*:[a-fA-F0-9:]+\]?'
514
+ port = r'(?::\d+)?' # optional port
515
+ path = r'(?:/?|[/?]\S+)$'
516
+ regex_url = r'%s(%s|%s|%s|%s)%s%s' % (protocol, domain, localhost, ipv4, ipv6, port, path)
517
+ return check(regex_url, candidate)
518
+
519
+
520
+ def check(regexp, candidate, maxLength=None):
521
+ if maxLength is not None:
522
+ assert len(candidate) <= maxLength, \
523
+ "%s is longer than max length (%s) allowed" % (candidate, maxLength)
524
+ assert re.compile(regexp).match(candidate) is not None, \
525
+ "'%s' does not match regular expression %s" % (candidate, regexp)
526
+ return True
527
+
528
+
529
+ def parseLFN(candidate):
530
+ """
531
+ _parseLFN_
532
+
533
+ Take an LFN, return the component parts
534
+ """
535
+ separator = "/"
536
+
537
+ # First, make sure what we've gotten is a real LFN
538
+ lfn(candidate)
539
+
540
+ parts = candidate.split('/')
541
+ final = {}
542
+
543
+ if parts[0] == '':
544
+ parts.remove('')
545
+ if 'user' in parts[1:3] or 'group' in parts[1:3]:
546
+ if parts[1] in ['user', 'group']:
547
+ final['baseLocation'] = '/%s' % separator.join(parts[:2])
548
+ parts = parts[2:]
549
+ else:
550
+ final['baseLocation'] = '/%s' % separator.join(parts[:3])
551
+ parts = parts[3:]
552
+
553
+ final['hnName'] = parts[0]
554
+ final['primaryDataset'] = parts[1]
555
+ final['secondaryDataset'] = parts[2]
556
+ final['processingVersion'] = parts[3]
557
+ final['lfnCounter'] = parts[4]
558
+ final['filename'] = parts[5]
559
+
560
+ return final
561
+
562
+ if len(parts) == 8:
563
+ # Then we have only two locations
564
+ final['baseLocation'] = '/%s' % separator.join(parts[:2])
565
+ parts = parts[2:]
566
+ elif len(parts) == 9:
567
+ final['baseLocation'] = '/%s' % separator.join(parts[:3])
568
+ parts = parts[3:]
569
+ else:
570
+ # How did we end up here?
571
+ # Something just went wrong
572
+ msg = """CRITICAL! This machine has experienced a complete logic failure while parsing LFNs.\n
573
+ If you are a developer this indicates that you have changed the Lexicon LFN regexp functions without changing the parsing.\n
574
+ If you are an operator, this indicates that this machine is likely unstable.\n
575
+ All data should be backed up and the machine removed from production for examination.\n"""
576
+ msg += "Candidate: %s" % candidate
577
+ raise WMException(msg)
578
+
579
+ final['acquisitionEra'] = parts[0]
580
+ final['primaryDataset'] = parts[1]
581
+ final['dataTier'] = parts[2]
582
+ final['processingVersion'] = parts[3]
583
+ final['lfnCounter'] = parts[4]
584
+ final['filename'] = parts[5]
585
+
586
+ return final
587
+
588
+
589
+ def parseLFNBase(candidate):
590
+ """
591
+ _parseLFNBase_
592
+
593
+ Return a meaningful dictionary with info from an LFNBase
594
+ """
595
+ separator = "/"
596
+
597
+ # First, make sure what we've gotten is a real LFNBase
598
+ lfnBase(candidate)
599
+
600
+ parts = candidate.split('/')
601
+ final = {}
602
+
603
+ if parts[0] == '':
604
+ parts.remove('')
605
+
606
+ if 'user' in parts[1:3] or 'group' in parts[1:3]:
607
+ if parts[1] in ['user', 'group']:
608
+ final['baseLocation'] = '/%s' % separator.join(parts[:2])
609
+ parts = parts[2:]
610
+ else:
611
+ final['baseLocation'] = '/%s' % separator.join(parts[:3])
612
+ parts = parts[3:]
613
+
614
+ final['hnName'] = parts[0]
615
+ final['primaryDataset'] = parts[1]
616
+ final['secondaryDataset'] = parts[2]
617
+ final['processingVersion'] = parts[3]
618
+
619
+ return final
620
+
621
+ if len(parts) == 6:
622
+ # Then we have only two locations
623
+ final['baseLocation'] = '/%s' % separator.join(parts[:2])
624
+ parts = parts[2:]
625
+ elif len(parts) == 7:
626
+ final['baseLocation'] = '/%s' % separator.join(parts[:3])
627
+ parts = parts[3:]
628
+ else:
629
+ # How did we end up here?
630
+ # Something just went wrong
631
+ msg = """CRITICAL! This machine has experienced a complete logic failure while parsing LFNs.\n
632
+ If you are a developer this indicates that you have changed the Lexicon LFN regexp functions without changing the parsing.\n
633
+ If you are an operator, this indicates that this machine is likely unstable.\n
634
+ All data should be backed up and the machine removed from production for examination.\n"""
635
+ msg += "Candidate: %s" % candidate
636
+ raise WMException(msg)
637
+
638
+ final['acquisitionEra'] = parts[0]
639
+ final['primaryDataset'] = parts[1]
640
+ final['dataTier'] = parts[2]
641
+ final['processingVersion'] = parts[3]
642
+
643
+ return final
644
+
645
+
646
+ def sanitizeURL(url):
647
+ """Take the url with/without username and password and return sanitized url,
648
+ username and password in dict format
649
+ WANNING: This doesn't check the correctness of url format.
650
+ Don't use ':' in username or password.
651
+ """
652
+ endpoint_components = urlparse(url)
653
+ # Cleanly pull out the user/password from the url
654
+ if endpoint_components.port:
655
+ netloc = '%s:%s' % (endpoint_components.hostname,
656
+ endpoint_components.port)
657
+ else:
658
+ netloc = endpoint_components.hostname
659
+
660
+ # Build a URL without the username/password information
661
+ url = urlunparse(
662
+ [endpoint_components.scheme,
663
+ netloc,
664
+ endpoint_components.path,
665
+ endpoint_components.params,
666
+ endpoint_components.query,
667
+ endpoint_components.fragment])
668
+
669
+ return {'url': url, 'username': endpoint_components.username,
670
+ 'password': endpoint_components.password}
671
+
672
+
673
+ def replaceToSantizeURL(url_str):
674
+ """
675
+ Take arbitrary string and search for urls with user and password and
676
+ replace it with sanitized url.
677
+ """
678
+
679
+ def _repUrl(matchObj):
680
+ return matchObj.group(1) + matchObj.group(4)
681
+
682
+ # TODO: won't catch every case (But is it good enough (trade off to performance)?)
683
+ urlRegExpr = r'\b(((?i)http|https|ftp|mysql|oracle|sqlite)+://)([^:]+:[^@]+@)(\S+)\b'
684
+ return re.sub(urlRegExpr, _repUrl, url_str)
685
+
686
+
687
+ def splitCouchServiceURL(serviceURL):
688
+ """
689
+ split service URL to couchURL and couchdb name
690
+ serviceURL should be couchURL/dbname format.
691
+ """
692
+
693
+ splitedURL = serviceURL.rstrip('/').rsplit('/', 1)
694
+ return splitedURL[0], splitedURL[1]
695
+
696
+
697
+ def primaryDatasetType(candidate):
698
+ pDatasetTypes = ["mc", "data", "cosmic", "test"]
699
+ if candidate in pDatasetTypes:
700
+ return True
701
+ # to sync with the check() exception when it doesn't match
702
+ raise AssertionError("Invalid primary dataset type : %s should be 'mc' or 'data' or 'test'" % candidate)
703
+
704
+
705
+ def subRequestType(candidate):
706
+ subTypes = ["MC", "ReDigi", "Extension", "Pilot", "RelVal", "HIRelVal", "ReReco", ""]
707
+ if candidate in subTypes:
708
+ return True
709
+ # to sync with the check() exception when it doesn't match
710
+ msg = "Invalid SubRequestType value: '{}'. Allowed values are: {}".format(candidate, subTypes)
711
+ raise AssertionError(msg)
712
+
713
+
714
+ def activity(candidate):
715
+ dashboardActivities = ['reprocessing', 'production', 'relval', 'tier0', 't0',
716
+ 'harvesting', 'storeresults', 'integration',
717
+ 'test', 'analysis']
718
+ if candidate in dashboardActivities:
719
+ return True
720
+ raise AssertionError("Invalid dashboard activity: %s should 'test'" % candidate)
721
+
722
+
723
+ def gpuParameters(candidate):
724
+ """
725
+ Validate the spec "GPUParams" argument, which is a JSON encoded object, thus:
726
+ * an encoded None object (like 'null')
727
+ * an encoded dictionary with the following parameters:
728
+ * mandatory: GPUMemoryMB (int), CUDARuntime (str), CUDACapabilities (list of str)
729
+ * optional: GPUName (str), CUDADriverVersion (str), CUDARuntimeVersion (str)
730
+ :param candidate: a JSON encoded data to be validated
731
+ :return: True if validation succeeded, False or exception otherwise
732
+ """
733
+ mandatoryArgs = set(["GPUMemoryMB", "CUDARuntime", "CUDACapabilities"])
734
+ optionalArgs = set(["GPUName", "CUDADriverVersion", "CUDARuntimeVersion"])
735
+ try:
736
+ data = json.loads(candidate)
737
+ except Exception:
738
+ raise AssertionError("GPUParams is not a valid JSON object")
739
+ # once python2 code is deprecated, this is the way to raise only the last exception
740
+ # raise AssertionError("GPUParams is not a valid JSON object") from None
741
+ if data is None:
742
+ return True
743
+ if not isinstance(data, dict):
744
+ raise AssertionError("GPUParams is not a dictionary encoded as JSON object")
745
+
746
+ paramSet = set(viewkeys(data))
747
+ # is every mandatory argument also in the provided args?
748
+ if not mandatoryArgs <= paramSet:
749
+ msg = "GPUParams does not contain all the mandatory arguments. "
750
+ msg +="Mandatory args: {}, while args provided are: {}".format(mandatoryArgs, paramSet)
751
+ raise AssertionError(msg)
752
+ # are there unknown arguments in the data provided?
753
+ unknownArgs = paramSet - mandatoryArgs - optionalArgs
754
+ if unknownArgs:
755
+ msg = "GPUParams contains arguments that are not supported. Args provided: {}, ".format(paramSet)
756
+ msg +="while mandatory args are: {} and optional args are: {}".format(mandatoryArgs, optionalArgs)
757
+ raise AssertionError(msg)
758
+ return _gpuInternalParameters(data)
759
+
760
+
761
+ CUDA_VERSION_REGEX = {"re": r"^\d+\.\d+(\.\d+)?$", "maxLength": 100}
762
+ def _gpuInternalParameters(candidate):
763
+ """
764
+ NOTE: this function is supposed to be called only from gpuParameters, which already
765
+ does the high level validation.
766
+ List of **required** parameters is:
767
+ * `GPUMemoryMB`: integer with the amount of memory, in Megabytes (MB). Validate as `> 0`. E.g.: 8000
768
+ * `CUDACapabilities`: a list of short strings (<= 100 chars). Validation should ensure at least one item
769
+ in the list and matching this regex: `r"^\d+.\d$"`. E.g.: ["7.5", "8.0"]
770
+ * `CUDARuntime`: a short string (<=100 chars) with the runtime version.
771
+ Validated against this regex: `r"^\d+.\d+$"`. E.g.: "11.2"
772
+ List of **optional** parameters is:
773
+ * `GPUName`: a string with the GPU name. Validate against `<= 100 chars`. E.g. "Tesla T4", "Quadro RTX 6000";
774
+ * `CUDADriverVersion`: a string with the CUDA driver version.
775
+ Validated against this regex: `r"^\d+.\d+\d+$"`E.g. "460.32.03"
776
+ * `CUDARuntimeVersion`: a string with the CUDA runtime version.
777
+ Validated against this regex: `r"^\d+.\d+\d+$"`E.g. "11.2.152"
778
+
779
+ This function validates all the internal key/value pairs provided for the GPUParams
780
+ argument, mostly against their own regular expressions.
781
+ :param candidate: the JSON object already decoded (thus, str or dict)
782
+ :return: True if validation succeeded, False or exception otherwise
783
+ """
784
+ # Generic regular expression for CUDA runtime/driver version
785
+ # It matches either something like "11.2", or "11.2.231"
786
+ # GPUMemoryMB validation
787
+ if not isinstance(candidate["GPUMemoryMB"], int) or not candidate["GPUMemoryMB"] > 0:
788
+ raise AssertionError("Mandatory GPUParams.GPUMemoryMB must be an integer and greater than 0")
789
+ # CUDACapabilities validation
790
+ if not isinstance(candidate["CUDACapabilities"], (list, set)) or not candidate["CUDACapabilities"]:
791
+ raise AssertionError("Mandatory GPUParams.CUDACapabilities must be a non-empty list")
792
+ for cudaCapabItem in candidate["CUDACapabilities"]:
793
+ if not isinstance(cudaCapabItem, (str, bytes)):
794
+ raise AssertionError("Mandatory GPUParams.CUDACapabilities must be a list of strings")
795
+ check(CUDA_VERSION_REGEX["re"], cudaCapabItem, CUDA_VERSION_REGEX["maxLength"])
796
+ # CUDARuntime validation
797
+ if not isinstance(candidate["CUDARuntime"], (str, bytes)) or\
798
+ not check(CUDA_VERSION_REGEX["re"], candidate["CUDARuntime"], CUDA_VERSION_REGEX["maxLength"]):
799
+ raise AssertionError("Mandatory GPUParams.CUDARuntime must be a string and shorter than 100 chars")
800
+
801
+ ### And now, validate the optional arguments
802
+ # GPUName validation
803
+ if "GPUName" in candidate:
804
+ if not isinstance(candidate["GPUName"], (str, bytes)):
805
+ raise AssertionError("Optional GPUParams.GPUName must be a string")
806
+ check(r".*", candidate["GPUName"], 100)
807
+ # CUDADriverVersion validation
808
+ if "CUDADriverVersion" in candidate:
809
+ if not isinstance(candidate["CUDADriverVersion"], (str, bytes)):
810
+ raise AssertionError("Optional GPUParams.CUDADriverVersion must be a string")
811
+ check(CUDA_VERSION_REGEX["re"], candidate["CUDADriverVersion"], CUDA_VERSION_REGEX["maxLength"])
812
+ # CUDARuntimeVersion validation
813
+ if "CUDARuntimeVersion" in candidate:
814
+ if not isinstance(candidate["CUDARuntimeVersion"], (str, bytes)):
815
+ raise AssertionError("Optional GPUParams.CUDARuntimeVersion must be a string")
816
+ check(CUDA_VERSION_REGEX["re"], candidate["CUDARuntimeVersion"], CUDA_VERSION_REGEX["maxLength"])
817
+ return True
818
+
819
+
820
+ def getStringsBetween(start, end, source):
821
+ """
822
+ get the string between start string and end string for given source string
823
+ source string is one line string (no new line charactor in it)
824
+ """
825
+ regex = r"\%s(.*?)\%s" % (start, end)
826
+ result = re.match(regex, source)
827
+ if result:
828
+ return result.group(1).strip()
829
+ else:
830
+ return None
831
+
832
+
833
+ def getIterMatchObjectOnRegexp(filePath, regexp):
834
+ with io.open(filePath, 'r', encoding='utf8', errors='ignore') as f:
835
+ for m in re.finditer(regexp, f.read()):
836
+ yield m