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,382 @@
1
+ """
2
+ _WMWorkloadTools_
3
+
4
+ Define some generic tools used by the StdSpecs and WMWorkload
5
+ to validate arguments that modify a WMWorkload and/or WMTask.
6
+
7
+ Created on Jun 13, 2013
8
+
9
+ @author: dballest
10
+ """
11
+ from builtins import str, bytes
12
+ from future.utils import viewitems, viewvalues
13
+
14
+ import json
15
+ import re
16
+ import inspect
17
+
18
+ from Utils.Utilities import makeList
19
+ from WMCore.DataStructs.LumiList import LumiList
20
+ from WMCore.WMSpec.WMSpecErrors import WMSpecFactoryException
21
+
22
+ def checkMemCore(paramInfo, minValue=1):
23
+ """
24
+ Spec validation function for the Memory/Multicore parameters
25
+ :param memInfo: memory provided by the user (can be an int/float/dict)
26
+ :param minValue: base value to be used to validate user's values
27
+ :return: True if validation is successful, raise an exception otherwise
28
+ """
29
+ try:
30
+ if isinstance(paramInfo, dict):
31
+ for value in viewvalues(paramInfo):
32
+ assert value >= minValue
33
+ else:
34
+ assert paramInfo >= minValue
35
+ except Exception:
36
+ return False
37
+ return True
38
+
39
+
40
+ def checkEventStreams(streamsInfo):
41
+ """
42
+ Spec validation function for the EventStreams parameter
43
+ :param streamsInfo: event streams provided by the user (can be either int or a dict)
44
+ :return: True if validation is successful, raise an exception otherwise
45
+ """
46
+ return checkMemCore(streamsInfo, 0)
47
+
48
+
49
+ def checkTimePerEvent(tpEvtInfo):
50
+ """
51
+ Spec validation function for the TimePerEvent parameter
52
+ :param tpEvtInfo: time per event provided by the user (can be either float or a dict)
53
+ :return: True if validation is successful, raise an exception otherwise
54
+ """
55
+ return checkMemCore(tpEvtInfo, 0)
56
+
57
+
58
+ def makeLumiList(lumiDict):
59
+ try:
60
+ if isinstance(lumiDict, (str, bytes)):
61
+ lumiDict = json.loads(lumiDict)
62
+ ll = LumiList(compactList=lumiDict)
63
+ return ll.getCompactList()
64
+ except Exception:
65
+ raise WMSpecFactoryException("Could not parse LumiList, %s: %s" % (type(lumiDict), lumiDict))
66
+
67
+
68
+ def parsePileupConfig(mcPileup, dataPileup):
69
+ """
70
+ _parsePileupConfig_
71
+
72
+ If the pileup config is defined as MCPileup and DataPileup
73
+ then make sure we get the usual dictionary as
74
+ PileupConfig : {'mc': ['/mc_pd/procds/tier'], 'data': ['/data_pd/procds/tier']}
75
+ """
76
+ pileUpConfig = {}
77
+ if mcPileup is not None:
78
+ pileUpConfig['mc'] = [mcPileup]
79
+ if dataPileup is not None:
80
+ pileUpConfig['data'] = [dataPileup]
81
+ return pileUpConfig
82
+
83
+
84
+ def _validateArgument(argument, value, argumentDefinition):
85
+ """
86
+ Validate a single argument against its definition in the spec
87
+ """
88
+ validNull = argumentDefinition["null"]
89
+ if not validNull and value is None:
90
+ raise WMSpecFactoryException("Argument '%s' cannot be None" % argument)
91
+ elif value is None:
92
+ return value
93
+
94
+ # is it a built-in type (int, str, bool, etc.) or a custom function
95
+ expected_type = argumentDefinition["type"]
96
+ try:
97
+ if expected_type == str and not isinstance(value, str):
98
+ raise TypeError(f"Argument '{argument}' with value {value} is not a string")
99
+ else:
100
+ # for other data types (or custom functions), just try to cast it to the expected type
101
+ value = expected_type(value)
102
+ except (ValueError, TypeError) as e:
103
+ msg = "Argument '%s' with value %r, has an incorrect data type: " % (argument, value)
104
+ msg += "%s. It must be convertible by %s" % (type(value), expected_type.__name__)
105
+ if str(e):
106
+ msg += f" (Error: {e})"
107
+ raise WMSpecFactoryException(msg) from None
108
+ except Exception as e:
109
+ msg = f"Generic exception raised during argument validation for argument: {argument} "
110
+ msg += "with value: %r. Error details: %s" % (value, str(e))
111
+ raise WMSpecFactoryException(msg) from None
112
+
113
+ _validateArgFunction(argument, value, argumentDefinition["validate"])
114
+ return value
115
+
116
+
117
+ def _validateArgumentDict(argument, argValue, argumentDefinition):
118
+ """
119
+ Validate only the basic structure of dict arguments, we anyways
120
+ don't have the definition of the internal arguments.
121
+ """
122
+ # make sure we're not going to cast a dict to string and let that unnoticed
123
+ if isinstance(argumentDefinition["type"], type(dict)) and not isinstance(argValue, dict):
124
+ msg = "Argument '%s' with value %r, has an incorrect data type: " % (argument, argValue)
125
+ msg += "%s. It must be %s" % (type(argValue), argumentDefinition["type"])
126
+ raise WMSpecFactoryException(msg)
127
+
128
+ # still an exception, make sure it has the correct format
129
+ if argument == "LumiList":
130
+ argValue = argumentDefinition["type"](argValue)
131
+
132
+ _validateArgFunction(argument, argValue, argumentDefinition["validate"])
133
+ return argValue
134
+
135
+
136
+ def _validateArgFunction(argument, value, valFunction):
137
+ """
138
+ Perform the validation function as in the argument definition
139
+ """
140
+ if valFunction:
141
+ try:
142
+ if not valFunction(value):
143
+ msg = "Argument '%s' with value %r, doesn't pass the validate function." % (argument, value)
144
+ msg += "\nIt's definition is:\n%s" % inspect.getsource(valFunction)
145
+ raise WMSpecFactoryException(msg)
146
+ except WMSpecFactoryException:
147
+ # just re-raise it to keep the error message clear
148
+ raise
149
+ except Exception as ex:
150
+ # Some validation functions (e.g. Lexicon) will raise errors instead of returning False
151
+ raise WMSpecFactoryException(str(ex))
152
+ return
153
+
154
+
155
+ def _validateArgumentOptions(arguments, argumentDefinition, optionKey=None):
156
+ """
157
+ Check whether create or assign mandatory parameters were properly
158
+ set in the request schema.
159
+ """
160
+ for arg, argDef in viewitems(argumentDefinition):
161
+ optional = argDef.get(optionKey, True)
162
+ if not optional and arg not in arguments:
163
+ msg = "Argument '{}' is mandatory and must be provided by the user.".format(arg)
164
+ msg += " Its definition is: {}".format(argDef)
165
+ raise WMSpecFactoryException(msg)
166
+ # specific case when user GUI returns empty string for optional arguments
167
+ elif arg not in arguments:
168
+ continue
169
+ elif isinstance(arguments[arg], dict):
170
+ arguments[arg] = _validateArgumentDict(arg, arguments[arg], argDef)
171
+ else:
172
+ arguments[arg] = _validateArgument(arg, arguments[arg], argDef)
173
+ return
174
+
175
+
176
+ def validateInputDatasSetAndParentFlag(arguments):
177
+ """
178
+ Check if the InputDataset value provided corresponds to an actual dataset in DBS.
179
+ If parent flag is provided, then check whether the input dataset has a parent.
180
+ the InputDataset existence in DBS and its parent, if needed.
181
+ """
182
+ inputdataset = _getChainKey(arguments, "InputDataset")
183
+ mcpileup = _getChainKey(arguments, "MCPileup")
184
+ datapileup = _getChainKey(arguments, "DataPileup")
185
+ includeParents = _getChainKey(arguments, "IncludeParents")
186
+ # TODO: this replace can be removed in one year from now, thus March 2022
187
+ dbsURL = arguments.get("DbsUrl")
188
+ if dbsURL:
189
+ dbsURL = dbsURL.replace("cmsweb.cern.ch", "cmsweb-prod.cern.ch")
190
+ dbsURL = dbsURL.rstrip("/")
191
+
192
+ if includeParents and not inputdataset:
193
+ msg = "IncludeParents flag is True but InputDataset value has not been provided"
194
+ raise WMSpecFactoryException(msg)
195
+
196
+ if dbsURL and inputdataset or mcpileup or datapileup:
197
+ # import DBS3Reader here, since Runtime code import this module and worker
198
+ # node doesn't have dbs3 client
199
+ from WMCore.Services.DBS.DBS3Reader import DBS3Reader
200
+ from WMCore.Services.DBS.DBSErrors import DBSReaderError
201
+ dbsInst = DBS3Reader(dbsURL)
202
+
203
+ try:
204
+ _datasetExists(dbsInst, inputdataset)
205
+ _datasetExists(dbsInst, mcpileup)
206
+ _datasetExists(dbsInst, datapileup)
207
+ except DBSReaderError as ex:
208
+ # we need to Wrap the exception to WMSpecFactoryException to be caught in reqmgr validation
209
+ raise WMSpecFactoryException(str(ex))
210
+
211
+ if includeParents:
212
+ try:
213
+ result = dbsInst.listDatasetParents(inputdataset)
214
+ if len(result) == 0:
215
+ msg = "IncludeParents flag is True but the input dataset %s has no parents" % inputdataset
216
+ raise DBSReaderError(msg)
217
+ except DBSReaderError as ex:
218
+ raise WMSpecFactoryException(str(ex))
219
+
220
+ return
221
+
222
+
223
+ def _datasetExists(dbsInst, inputData):
224
+ """
225
+ __datasetExists_
226
+
227
+ Check if dataset exists in DBS. Exception is raised in case it does not exist.
228
+ """
229
+ if inputData is None:
230
+ return
231
+ dbsInst.checkDatasetPath(inputData)
232
+ return
233
+
234
+
235
+ def _getChainKey(arguments, keyName):
236
+ """
237
+ Given a request arguments dictionary and a key name, properly returns its
238
+ value regardless of the request type.
239
+ """
240
+ if "TaskChain" in arguments:
241
+ value = arguments['Task1'].get(keyName)
242
+ elif "StepChain" in arguments:
243
+ value = arguments['Step1'].get(keyName)
244
+ else:
245
+ value = arguments.get(keyName)
246
+ return value
247
+
248
+
249
+ def _validateMoveSubscription(subType, sites):
250
+ """
251
+ Move subscriptions are only allowed to T0 or T1s, see #7760
252
+ """
253
+ invalidSites = [site for site in sites if re.match("^T[2-3]", site)]
254
+ if invalidSites:
255
+ msg = "Move subscription (%s) not allowed to T2/T3 sites: %s" % (subType, invalidSites)
256
+ raise WMSpecFactoryException(msg)
257
+
258
+
259
+ def validateSiteLists(arguments):
260
+ whiteList = arguments.get("SiteWhitelist", [])
261
+ blackList = arguments.get("SiteBlacklist", [])
262
+ whiteList = makeList(whiteList)
263
+ blackList = makeList(blackList)
264
+ res = (set(whiteList) & set(blackList))
265
+ if len(res):
266
+ msg = "Validation failed: The same site cannot be white and blacklisted: %s" % list(res)
267
+ raise WMSpecFactoryException(msg)
268
+ # store the properly formatted values (list instead of string)
269
+ arguments["SiteWhitelist"] = whiteList
270
+ arguments["SiteBlacklist"] = blackList
271
+ return
272
+
273
+
274
+ def validateArgumentsCreate(arguments, argumentDefinition, checkInputDset=True):
275
+ """
276
+ _validateArguments_
277
+
278
+ Validate a set of arguments - for spec creation - against their
279
+ definition in StdBase.getWorkloadCreateArgs.
280
+
281
+ When validating Step/Task dictionary, checkInputDset should be usually
282
+ false since the input dataset validation already happened at top level.
283
+
284
+ It returns an error message if the validation went wrong,
285
+ otherwise returns None.
286
+ """
287
+ validateUnknownArgs(arguments, argumentDefinition)
288
+ _validateArgumentOptions(arguments, argumentDefinition, "optional")
289
+ if checkInputDset:
290
+ validateInputDatasSetAndParentFlag(arguments)
291
+ return
292
+
293
+
294
+ def validateArgumentsUpdate(arguments, argumentDefinition, optionKey="assign_optional"):
295
+ """
296
+ _validateArgumentsUpdate_
297
+
298
+ Validate a set of arguments - for spec assignment/update - against
299
+ their definition in StdBase.getWorkloadAssignArgs.
300
+
301
+ It returns an error message if the validation went wrong,
302
+ otherwise returns None.
303
+ """
304
+ validateUnknownArgs(arguments, argumentDefinition)
305
+ _validateArgumentOptions(arguments, argumentDefinition, optionKey)
306
+ validateSiteLists(arguments)
307
+
308
+ return
309
+
310
+ def validateUnknownArgs(arguments, argumentDefinition):
311
+ """
312
+ Make sure user is sending only arguments that are known by
313
+ StdBase.getWorkloadCreateArgs, otherwise fail spec creation.
314
+
315
+ It returns an error message if the validation went wrong,
316
+ otherwise returns None.
317
+ """
318
+ unknownArgs = set(arguments) - set(argumentDefinition.keys())
319
+ if unknownArgs:
320
+ # now onto the exceptions...
321
+ if arguments.get("RequestType") == "ReReco":
322
+ unknownArgs = unknownArgs - set([x for x in unknownArgs if x.startswith("Skim")])
323
+ elif arguments.get("RequestType") == "StepChain":
324
+ unknownArgs = unknownArgs - set([x for x in unknownArgs if x.startswith("Step")])
325
+ elif arguments.get("RequestType") == "TaskChain":
326
+ unknownArgs = unknownArgs - set([x for x in unknownArgs if x.startswith("Task")])
327
+ elif arguments.get("RequestType") == "Resubmission":
328
+ # oh well, then we have to skip all possible obscure arguments
329
+ unknownArgs = unknownArgs - set([x for x in unknownArgs if x.startswith("Skim")])
330
+ unknownArgs = unknownArgs - set([x for x in unknownArgs if x.startswith("Step")])
331
+ unknownArgs = unknownArgs - set([x for x in unknownArgs if x.startswith("Task")])
332
+
333
+ if unknownArgs:
334
+ msg = "There are unknown/unsupported arguments in your request spec: %s" % list(unknownArgs)
335
+ raise WMSpecFactoryException(msg)
336
+ return
337
+
338
+
339
+ def setArgumentsWithDefault(arguments, argumentDefinition):
340
+ """
341
+ Set arguments not provided by the user with a default spec value
342
+ """
343
+ for argument in argumentDefinition:
344
+ if argument not in arguments:
345
+ arguments[argument] = argumentDefinition[argument]["default"]
346
+
347
+ # set the Campaign default value to the same as AcquisitionEra if Campaign is not specified
348
+ if "Campaign" in argumentDefinition and not arguments.get("Campaign"):
349
+ if "AcquisitionEra" in arguments and isinstance(arguments["AcquisitionEra"], (str, bytes)):
350
+ arguments["Campaign"] = arguments["AcquisitionEra"]
351
+
352
+ return
353
+
354
+ def setAssignArgumentsWithDefault(arguments, argumentDefinition):
355
+ """
356
+ Set arguments not provided by the user with a default assign spec value,
357
+ unless the default value is None (read don't set default).
358
+ """
359
+ for argument in argumentDefinition:
360
+ if argument not in arguments and argumentDefinition[argument]["default"] is not None:
361
+ arguments[argument] = argumentDefinition[argument]["default"]
362
+
363
+ return
364
+
365
+ def loadSpecClassByType(specType):
366
+ factoryName = "%sWorkloadFactory" % specType
367
+ mod = __import__("WMCore.WMSpec.StdSpecs.%s" % specType,
368
+ globals(), locals(), [factoryName])
369
+ specClass = getattr(mod, factoryName)
370
+
371
+ return specClass
372
+
373
+
374
+ def loadSpecByType(specType):
375
+ specClass = loadSpecClassByType(specType)
376
+ return specClass()
377
+
378
+
379
+ def checkDBSURL(url):
380
+ # import DBS3Reader here, since Runtime code import this module and worker node doesn't have dbs3 client
381
+ from WMCore.Services.DBS.DBS3Reader import DBS3Reader
382
+ return DBS3Reader(url).checkDBSServer()
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ _WMCore.WMSpec_
4
+
5
+ """
6
+
7
+
8
+
9
+ __all__ = []
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env python
2
+ """Map data to locations for WorkQueue"""
3
+
4
+ from future.utils import viewitems, viewvalues, listvalues
5
+ from builtins import object
6
+ from future import standard_library
7
+ standard_library.install_aliases()
8
+
9
+ from collections import defaultdict
10
+ import logging
11
+
12
+ from urllib.parse import urlparse
13
+
14
+ from WMCore.Services.DBS.DBSReader import DBSReader
15
+ from WMCore.Services.MSUtils.MSUtils import getPileupDocs
16
+ from WMCore.WorkQueue.DataStructs.ACDCBlock import ACDCBlock
17
+
18
+ # TODO: Combine with existing dls so DBSreader can do this kind of thing transparently
19
+ # TODO: Known Issue: Can't have same item in multiple dbs's at the same time.
20
+
21
+
22
+ def isGlobalDBS(dbs):
23
+ """
24
+ Receives a DBSReader object and finds out whether it's
25
+ pointing to Global DBS (no matter whether it's production
26
+ or the pre-production instance).
27
+ """
28
+ try:
29
+ url = urlparse(dbs.dbsURL)
30
+ if url.hostname.startswith('cmsweb'):
31
+ if url.path.startswith('/dbs/prod/global') or url.path.startswith('/dbs/int/global'):
32
+ return True
33
+ except Exception as ex:
34
+ logging.error("Failed to find out whether DBS is Global or not. Error: %s", str(ex))
35
+ return False
36
+
37
+
38
+ def isDataset(inputData):
39
+ """Check whether we're handling a block or a dataset"""
40
+ if '#' in inputData.split('/')[-1]:
41
+ return False
42
+ return True
43
+
44
+
45
+ class DataLocationMapper(object):
46
+ """Map data to locations for WorkQueue"""
47
+
48
+ def __init__(self, logger=None, **kwargs):
49
+ self.params = kwargs
50
+ self.logger = logger or logging.getLogger()
51
+ self.params.setdefault('locationFrom', 'subscription')
52
+ self.params.setdefault('incompleteBlocks', False)
53
+ self.params.setdefault('requireBlocksSubscribed', True)
54
+ self.params.setdefault('rucioAccount', "wmcore_transferor")
55
+ self.params.setdefault('rucioAccountPU', "wmcore_pileup")
56
+
57
+ validLocationFrom = ('subscription', 'location')
58
+ if self.params['locationFrom'] not in validLocationFrom:
59
+ msg = "Invalid value for locationFrom: '%s'. Valid values are: %s" % (
60
+ self.params['locationFrom'], validLocationFrom)
61
+ raise ValueError(msg)
62
+
63
+ self.rucio = self.params.get('rucio')
64
+ if self.params.get('cric'):
65
+ self.cric = self.params['cric']
66
+
67
+ # save each DBSReader instance in the class object, such that
68
+ # the same object is not shared amongst multiple threads
69
+ self.dbses = {}
70
+
71
+ def __call__(self, dataItems, rucioAcct=None):
72
+ rucioAcct = rucioAcct or self.params['rucioAccount']
73
+ result = {}
74
+
75
+ dataByDbs = self.organiseByDbs(dataItems)
76
+
77
+ for dbs, dataItems in viewitems(dataByDbs):
78
+ # if global use Rucio, else use dbs
79
+ if "pileup" in rucioAcct:
80
+ output = self.locationsFromMSPileup(dataItems, dbs.dbsURL)
81
+ elif isGlobalDBS(dbs):
82
+ output = self.locationsFromRucio(dataItems, rucioAcct)
83
+ else:
84
+ output = self.locationsFromDBS(dbs, dataItems)
85
+ result[dbs] = output
86
+
87
+ return result
88
+
89
+ def locationsFromRucio(self, dataItems, rucioAcct):
90
+ """
91
+ Get data location from Rucio. Location is mapped to the actual
92
+ sites associated with them, so PSNs are actually returned
93
+ :param dataItems: list of datasets/blocks names
94
+ :param rucioAcct: string with the Rucio account name to check the rules against
95
+ :return: dictionary key'ed by the dataset/block, with a list of PSNs as value
96
+ """
97
+ result = defaultdict(set)
98
+ self.logger.info("Fetching location from Rucio for account: %s", rucioAcct)
99
+ for dataItem in dataItems:
100
+ try:
101
+ dataLocations = self.rucio.getDataLockedAndAvailable(name=dataItem,
102
+ account=rucioAcct)
103
+ # resolve the PNNs into PSNs
104
+ result[dataItem] = self.cric.PNNstoPSNs(dataLocations)
105
+ except Exception as ex:
106
+ self.logger.error('Error getting block location from Rucio for %s: %s', dataItem, str(ex))
107
+
108
+ return result
109
+
110
+ def locationsFromDBS(self, dbs, dataItems):
111
+ """Get data location from dbs"""
112
+ result = defaultdict(set)
113
+ for dataItem in dataItems:
114
+ try:
115
+ if isDataset(dataItem):
116
+ phedexNodeNames = dbs.listDatasetLocation(dataItem)
117
+ else:
118
+ phedexNodeNames = dbs.listFileBlockLocation(dataItem)
119
+ result[dataItem].update(phedexNodeNames)
120
+ except Exception as ex:
121
+ self.logger.error('Error getting block location from dbs for %s: %s', dataItem, str(ex))
122
+
123
+ # convert the sets to lists
124
+ for name, nodes in viewitems(result):
125
+ psns = set()
126
+ psns.update(self.cric.PNNstoPSNs(nodes))
127
+ result[name] = list(psns)
128
+
129
+ return result
130
+
131
+ def locationsFromMSPileup(self, dataItems, dbsUrl):
132
+ """
133
+ Get data location from MSPileup.
134
+
135
+ :param dataItems: list, list of pileup names to query
136
+ :param dbsUrl: str, dbs url to check which dbs server
137
+ :return: dict, dict of pileup name keys with location set values
138
+ """
139
+ self.logger.info(f'Fetching locations from MSPileup for {len(dataItems)} containers')
140
+
141
+ result = defaultdict(set)
142
+ # TODO: Fetch multiple pileups in single request
143
+ for dataItem in dataItems:
144
+ try:
145
+ queryDict = {'query': {'pileupName': dataItem},
146
+ 'filters': ['currentRSEs', 'pileupName', 'containerFraction', 'ruleIds']}
147
+ pileupInstance = '-testbed' if 'cmsweb-testbed' in dbsUrl else '-prod'
148
+ msPileupUrl = f"https://cmsweb{pileupInstance}.cern.ch/ms-pileup/data/pileup"
149
+ doc = getPileupDocs(msPileupUrl, queryDict, method='POST')[0]
150
+ self.logger.info(f'locationsFromPileup - name: {dataItem}, currentRSEs: {doc["currentRSEs"]}, containerFraction: {doc["containerFraction"]}')
151
+ # resolve PNNs into PSNs
152
+ result[dataItem] = self.cric.PNNstoPSNs(doc['currentRSEs'])
153
+ except IndexError:
154
+ self.logger.error('Did not find any pileup document for query: %s', queryDict['query'])
155
+ except Exception as ex:
156
+ self.logger.error('Error getting block location from MSPileup for %s: %s', dataItem, str(ex))
157
+
158
+ return result
159
+
160
+ def organiseByDbs(self, dataItems):
161
+ """Sort items by dbs instances - return dict with DBSReader as key & data items as values"""
162
+ itemsByDbs = defaultdict(list)
163
+ for item in dataItems:
164
+ if ACDCBlock.checkBlockName(item['name']):
165
+ # if it is acdc block don't update location. location should be
166
+ # inserted when block is queued and not supposed to change
167
+ continue
168
+
169
+ if item['dbs_url'] not in self.dbses:
170
+ self.dbses[item['dbs_url']] = DBSReader(item['dbs_url'])
171
+ itemsByDbs[self.dbses[item['dbs_url']]].append(item['name'])
172
+
173
+ return itemsByDbs
174
+
175
+
176
+ class WorkQueueDataLocationMapper(DataLocationMapper):
177
+ """WorkQueue data location functionality"""
178
+
179
+ def __init__(self, logger, backend, **kwargs):
180
+ self.backend = backend
181
+ self.logger = logger
182
+ super(WorkQueueDataLocationMapper, self).__init__(logger, **kwargs)
183
+
184
+ def __call__(self):
185
+ elemUpdated = 0
186
+ elemUpdated += self.updatePrimaryLocation()
187
+ elemUpdated += self.updateParentLocation()
188
+ elemUpdated += self.updatePileupLocation()
189
+
190
+ return elemUpdated
191
+
192
+ def updatePrimaryLocation(self):
193
+ dataItems = self.backend.getActiveData()
194
+ dataLocations = super(WorkQueueDataLocationMapper, self).__call__(dataItems)
195
+ self.logger.info("Found %d unique input data to update location", len(dataItems))
196
+
197
+ # elements with multiple changed data items will fail fix this, or move to store data outside element
198
+ modified = []
199
+ for dataMapping in viewvalues(dataLocations):
200
+ for data, locations in viewitems(dataMapping):
201
+ elements = self.backend.getElementsForData(data)
202
+ for element in elements:
203
+ if element.get('NoInputUpdate', False):
204
+ continue
205
+ if sorted(locations) != sorted(element['Inputs'][data]):
206
+ self.logger.info("%s, setting location to: %s", data, locations)
207
+ element['Inputs'][data] = locations
208
+ modified.append(element)
209
+ self.logger.info("Updating %d elements for Input location update", len(modified))
210
+ self.backend.saveElements(*modified)
211
+
212
+ return len(modified)
213
+
214
+ def updateParentLocation(self):
215
+ dataItems = self.backend.getActiveParentData()
216
+
217
+ # fullResync incorrect with multiple dbs's - fix!!!
218
+ dataLocations = DataLocationMapper.__call__(self, dataItems)
219
+ self.logger.info("Found %d unique parent data to update location", len(dataItems))
220
+
221
+ # Given that there might be multiple data items to be updated
222
+ # handle it like a dict such that element lookup becomes easier
223
+ modified = {}
224
+ for dataMapping in viewvalues(dataLocations):
225
+ for data, locations in viewitems(dataMapping):
226
+ elements = self.backend.getElementsForParentData(data)
227
+ for element in elements:
228
+ if element.get('NoInputUpdate', False):
229
+ continue
230
+ if element.id in modified:
231
+ element = modified[element.id]
232
+ for pData in element['ParentData']:
233
+ if pData == data:
234
+ if sorted(locations) != sorted(element['ParentData'][pData]):
235
+ self.logger.info("%s, setting location to: %s", data, locations)
236
+ element['ParentData'][pData] = locations
237
+ modified[element.id] = element
238
+ break
239
+ self.logger.info("Updating %d elements for Parent location update", len(modified))
240
+ self.backend.saveElements(*listvalues(modified))
241
+
242
+ return len(modified)
243
+
244
+ def updatePileupLocation(self):
245
+ dataItems = self.backend.getActivePileupData()
246
+
247
+ # fullResync incorrect with multiple dbs's - fix!!!
248
+ dataLocations = DataLocationMapper.__call__(self, dataItems, self.params['rucioAccountPU'])
249
+ self.logger.info("Found %d unique pileup data to update location", len(dataItems))
250
+
251
+ # Given that there might be multiple data items to be updated
252
+ # handle it like a dict such that element lookup becomes easier
253
+ modified = {}
254
+ for dataMapping in listvalues(dataLocations):
255
+ for data, locations in viewitems(dataMapping):
256
+ elements = self.backend.getElementsForPileupData(data)
257
+ self.logger.info("Found %d elements using pileup: %s", len(elements), data)
258
+ for element in elements:
259
+ if element.get('NoPileupUpdate', False):
260
+ continue
261
+ if element.id in modified:
262
+ element = modified[element.id]
263
+ for pData in element['PileupData']:
264
+ if pData == data:
265
+ if sorted(locations) != sorted(element['PileupData'][pData]):
266
+ self.logger.info("%s, setting location to: %s", data, locations)
267
+ element['PileupData'][pData] = locations
268
+ modified[element.id] = element
269
+ break
270
+ self.logger.info("Updating %d elements for Pileup location update", len(modified))
271
+ self.backend.saveElements(*listvalues(modified))
272
+
273
+ return len(modified)