panda-server-source 0.8.0__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 (375) hide show
  1. panda_server_source-0.8.0.dist-info/METADATA +55 -0
  2. panda_server_source-0.8.0.dist-info/RECORD +375 -0
  3. panda_server_source-0.8.0.dist-info/WHEEL +4 -0
  4. panda_server_source-0.8.0.dist-info/licenses/LICENSE.txt +202 -0
  5. pandajedi/__init__.py +0 -0
  6. pandajedi/jedibrokerage/AtlasAnalJobBroker.py +2343 -0
  7. pandajedi/jedibrokerage/AtlasBrokerUtils.py +1292 -0
  8. pandajedi/jedibrokerage/AtlasProdJobBroker.py +2064 -0
  9. pandajedi/jedibrokerage/AtlasProdTaskBroker.py +629 -0
  10. pandajedi/jedibrokerage/GenJobBroker.py +381 -0
  11. pandajedi/jedibrokerage/JobBrokerBase.py +133 -0
  12. pandajedi/jedibrokerage/TaskBrokerBase.py +15 -0
  13. pandajedi/jedibrokerage/__init__.py +0 -0
  14. pandajedi/jediconfig/__init__.py +0 -0
  15. pandajedi/jediconfig/jedi_config.py +40 -0
  16. pandajedi/jedicore/FactoryBase.py +182 -0
  17. pandajedi/jedicore/Interaction.py +433 -0
  18. pandajedi/jedicore/JediDBProxy.py +56 -0
  19. pandajedi/jedicore/JediDBProxyPool.py +37 -0
  20. pandajedi/jedicore/JediDBSchemaInfo.py +17 -0
  21. pandajedi/jedicore/JediException.py +13 -0
  22. pandajedi/jedicore/JediTaskBuffer.py +984 -0
  23. pandajedi/jedicore/JediTaskBufferInterface.py +50 -0
  24. pandajedi/jedicore/MsgWrapper.py +124 -0
  25. pandajedi/jedicore/ProcessUtils.py +34 -0
  26. pandajedi/jedicore/SiteCandidate.py +90 -0
  27. pandajedi/jedicore/ThreadUtils.py +205 -0
  28. pandajedi/jedicore/__init__.py +0 -0
  29. pandajedi/jediddm/AtlasDDMClient.py +1708 -0
  30. pandajedi/jediddm/DDMClientBase.py +16 -0
  31. pandajedi/jediddm/DDMInterface.py +83 -0
  32. pandajedi/jediddm/GenDDMClient.py +17 -0
  33. pandajedi/jediddm/__init__.py +0 -0
  34. pandajedi/jedidog/AtlasAnalWatchDog.py +648 -0
  35. pandajedi/jedidog/AtlasDataCarouselWatchDog.py +189 -0
  36. pandajedi/jedidog/AtlasDataLocalityUpdaterWatchDog.py +215 -0
  37. pandajedi/jedidog/AtlasProdWatchDog.py +443 -0
  38. pandajedi/jedidog/AtlasQueueFillerWatchDog.py +800 -0
  39. pandajedi/jedidog/AtlasTaskWithholderWatchDog.py +245 -0
  40. pandajedi/jedidog/AtlasWorkflowManagerWatchDog.py +63 -0
  41. pandajedi/jedidog/GenWatchDog.py +21 -0
  42. pandajedi/jedidog/JumboWatchDog.py +147 -0
  43. pandajedi/jedidog/TypicalWatchDogBase.py +122 -0
  44. pandajedi/jedidog/WatchDogBase.py +53 -0
  45. pandajedi/jedidog/__init__.py +0 -0
  46. pandajedi/jediexec/reniceJEDI.py +25 -0
  47. pandajedi/jedigen/AtlasTaskGenerator.py +110 -0
  48. pandajedi/jedigen/TaskGeneratorBase.py +15 -0
  49. pandajedi/jedigen/__init__.py +0 -0
  50. pandajedi/jedimsgprocessor/__init__.py +0 -0
  51. pandajedi/jedimsgprocessor/ai_parameter_adjuster_msg_processor +71 -0
  52. pandajedi/jedimsgprocessor/atlas_idds_msg_processor.py +66 -0
  53. pandajedi/jedimsgprocessor/base_msg_processor.py +33 -0
  54. pandajedi/jedimsgprocessor/forwarding_msg_processor.py +29 -0
  55. pandajedi/jedimsgprocessor/hpo_msg_processor.py +93 -0
  56. pandajedi/jedimsgprocessor/jedi_contents_feeder_msg_processor.py +63 -0
  57. pandajedi/jedimsgprocessor/jedi_job_generator_msg_processor.py +185 -0
  58. pandajedi/jedimsgprocessor/jedi_post_processor_msg_processor.py +82 -0
  59. pandajedi/jedimsgprocessor/kafka_msg_processor.py +44 -0
  60. pandajedi/jedimsgprocessor/panda_callback_msg_processor.py +182 -0
  61. pandajedi/jedimsgprocessor/panda_to_jedi_msg_processor.py +74 -0
  62. pandajedi/jedimsgprocessor/processing_msg_processor.py +134 -0
  63. pandajedi/jedimsgprocessor/status_report_msg_processor.py +129 -0
  64. pandajedi/jedimsgprocessor/tape_carousel_msg_processor.py +118 -0
  65. pandajedi/jedimsgprocessor/workflow_manager_msg_processor.py +89 -0
  66. pandajedi/jediorder/ContentsFeeder.py +785 -0
  67. pandajedi/jediorder/JediDaemon.py +27 -0
  68. pandajedi/jediorder/JediKnight.py +55 -0
  69. pandajedi/jediorder/JediMaster.py +238 -0
  70. pandajedi/jediorder/JediMsgProcessor.py +32 -0
  71. pandajedi/jediorder/JobBroker.py +33 -0
  72. pandajedi/jediorder/JobGenerator.py +2763 -0
  73. pandajedi/jediorder/JobSplitter.py +308 -0
  74. pandajedi/jediorder/JobThrottler.py +28 -0
  75. pandajedi/jediorder/PostProcessor.py +166 -0
  76. pandajedi/jediorder/TaskBroker.py +268 -0
  77. pandajedi/jediorder/TaskCommando.py +334 -0
  78. pandajedi/jediorder/TaskGenerator.py +17 -0
  79. pandajedi/jediorder/TaskRefiner.py +611 -0
  80. pandajedi/jediorder/TaskSetupper.py +17 -0
  81. pandajedi/jediorder/WatchDog.py +79 -0
  82. pandajedi/jediorder/__init__.py +0 -0
  83. pandajedi/jedipprocess/AtlasAnalPostProcessor.py +404 -0
  84. pandajedi/jedipprocess/AtlasPostProcessorUtils.py +50 -0
  85. pandajedi/jedipprocess/AtlasProdPostProcessor.py +178 -0
  86. pandajedi/jedipprocess/GenPostProcessor.py +35 -0
  87. pandajedi/jedipprocess/MailTemplates.py +185 -0
  88. pandajedi/jedipprocess/PostProcessorBase.py +269 -0
  89. pandajedi/jedipprocess/__init__.py +0 -0
  90. pandajedi/jedirefine/AtlasAnalTaskRefiner.py +259 -0
  91. pandajedi/jedirefine/AtlasProdTaskRefiner.py +162 -0
  92. pandajedi/jedirefine/GenTaskRefiner.py +61 -0
  93. pandajedi/jedirefine/RefinerUtils.py +154 -0
  94. pandajedi/jedirefine/TaskRefinerBase.py +996 -0
  95. pandajedi/jedirefine/__init__.py +0 -0
  96. pandajedi/jedisetup/AtlasTaskSetupper.py +309 -0
  97. pandajedi/jedisetup/GenTaskSetupper.py +16 -0
  98. pandajedi/jedisetup/SimpleTaskSetupper.py +152 -0
  99. pandajedi/jedisetup/TaskSetupperBase.py +15 -0
  100. pandajedi/jedisetup/__init__.py +0 -0
  101. pandajedi/jeditest/SchemaChecker.py +41 -0
  102. pandajedi/jeditest/addContWoSoTask.py +54 -0
  103. pandajedi/jeditest/addDataCarouselRequest.py +47 -0
  104. pandajedi/jeditest/addEventServiceTask.py +101 -0
  105. pandajedi/jeditest/addHpoTask.py +81 -0
  106. pandajedi/jeditest/addIDDSStageInRequest.py +56 -0
  107. pandajedi/jeditest/addNonAtlasTask.py +71 -0
  108. pandajedi/jeditest/addNonAtlasTaskEnc.py +64 -0
  109. pandajedi/jeditest/addTestTask.py +124 -0
  110. pandajedi/jeditest/addTestTaskParamToDEFT.py +70 -0
  111. pandajedi/jeditest/addTestTaskWithMerger.py +97 -0
  112. pandajedi/jeditest/brokerTest.py +78 -0
  113. pandajedi/jeditest/cancelDataCarouselRequest.py +35 -0
  114. pandajedi/jeditest/contentsFeederTest.py +28 -0
  115. pandajedi/jeditest/contentsFeederTestWithTask.py +18 -0
  116. pandajedi/jeditest/ddmTest.py +4 -0
  117. pandajedi/jeditest/jobGenForOneTask.py +38 -0
  118. pandajedi/jeditest/jobGeneratorTest.py +43 -0
  119. pandajedi/jeditest/jobSplitterTest.py +104 -0
  120. pandajedi/jeditest/jobThrottlerTest.py +22 -0
  121. pandajedi/jeditest/msgProcessorTest.py +9 -0
  122. pandajedi/jeditest/postProcessorTest.py +18 -0
  123. pandajedi/jeditest/resubmitDataCarouselRequest.py +35 -0
  124. pandajedi/jeditest/resubmitTaskParam.py +20 -0
  125. pandajedi/jeditest/taskBrokerTest.py +22 -0
  126. pandajedi/jeditest/taskBrokerTestWithTask.py +38 -0
  127. pandajedi/jeditest/taskBufferTest.py +5 -0
  128. pandajedi/jeditest/taskCommandoTest.py +28 -0
  129. pandajedi/jeditest/taskRefinerTest.py +30 -0
  130. pandajedi/jeditest/testOneTaskToRefine.py +49 -0
  131. pandajedi/jeditest/testOneTaskToTaskBroker.py +42 -0
  132. pandajedi/jeditest/testPandaDDMMap.py +62 -0
  133. pandajedi/jeditest/updateDataCarouselRequestParams.py +50 -0
  134. pandajedi/jeditest/watchDogTest.py +25 -0
  135. pandajedi/jeditest/workQueueTest.py +22 -0
  136. pandajedi/jedithrottle/AtlasAnalJobThrottler.py +19 -0
  137. pandajedi/jedithrottle/AtlasProdJobThrottler.py +18 -0
  138. pandajedi/jedithrottle/GenJobThrottler.py +26 -0
  139. pandajedi/jedithrottle/JobThrottlerBase.py +496 -0
  140. pandajedi/jedithrottle/__init__.py +0 -0
  141. pandaserver/__init__.py +0 -0
  142. pandaserver/api/__init__.py +0 -0
  143. pandaserver/api/v1/__init__.py +0 -0
  144. pandaserver/api/v1/common.py +339 -0
  145. pandaserver/api/v1/credential_management_api.py +372 -0
  146. pandaserver/api/v1/data_carousel_api.py +264 -0
  147. pandaserver/api/v1/event_api.py +269 -0
  148. pandaserver/api/v1/file_server_api.py +942 -0
  149. pandaserver/api/v1/harvester_api.py +445 -0
  150. pandaserver/api/v1/http_client.py +166 -0
  151. pandaserver/api/v1/idds_api.py +180 -0
  152. pandaserver/api/v1/job_api.py +463 -0
  153. pandaserver/api/v1/metaconfig_api.py +122 -0
  154. pandaserver/api/v1/pilot_api.py +895 -0
  155. pandaserver/api/v1/statistics_api.py +207 -0
  156. pandaserver/api/v1/system_api.py +186 -0
  157. pandaserver/api/v1/task_api.py +1520 -0
  158. pandaserver/api/v1/tests/__init__.py +0 -0
  159. pandaserver/api/v1/tests/credential_management_api_tests.py +116 -0
  160. pandaserver/api/v1/tests/data_carousel_api_tests.py +82 -0
  161. pandaserver/api/v1/tests/harvester_api_tests.py +188 -0
  162. pandaserver/api/v1/tests/idds_api_tests.py +45 -0
  163. pandaserver/api/v1/tests/job_api_tests.py +112 -0
  164. pandaserver/api/v1/tests/pilot_api_tests.py +154 -0
  165. pandaserver/api/v1/tests/statistics_api_tests.py +104 -0
  166. pandaserver/api/v1/tests/system_api_tests.py +58 -0
  167. pandaserver/api/v1/tests/task_api_tests.py +590 -0
  168. pandaserver/api/v1/version.py +2 -0
  169. pandaserver/api/v1/workflow_api.py +136 -0
  170. pandaserver/brokerage/SiteMapper.py +406 -0
  171. pandaserver/brokerage/__init__.py +0 -0
  172. pandaserver/brokerage/broker.py +272 -0
  173. pandaserver/config/__init__.py +0 -0
  174. pandaserver/config/config_utils.py +15 -0
  175. pandaserver/config/daemon_config.py +29 -0
  176. pandaserver/config/mcp_config.py +38 -0
  177. pandaserver/config/panda_config.py +233 -0
  178. pandaserver/configurator/Carbon.py +65 -0
  179. pandaserver/configurator/Configurator.py +908 -0
  180. pandaserver/configurator/__init__.py +0 -0
  181. pandaserver/configurator/aux.py +73 -0
  182. pandaserver/daemons/__init__.py +0 -0
  183. pandaserver/daemons/master.py +110 -0
  184. pandaserver/daemons/master_systemd.py +79 -0
  185. pandaserver/daemons/scripts/__init__.py +0 -0
  186. pandaserver/daemons/scripts/add_main.py +264 -0
  187. pandaserver/daemons/scripts/add_sub.py +221 -0
  188. pandaserver/daemons/scripts/cache_pilots.py +47 -0
  189. pandaserver/daemons/scripts/cache_schedconfig.py +286 -0
  190. pandaserver/daemons/scripts/carbon.py +50 -0
  191. pandaserver/daemons/scripts/configurator.py +94 -0
  192. pandaserver/daemons/scripts/copyArchive.py +1387 -0
  193. pandaserver/daemons/scripts/datasetManager.py +1154 -0
  194. pandaserver/daemons/scripts/dummy_test.py +25 -0
  195. pandaserver/daemons/scripts/evpPD2P.py +144 -0
  196. pandaserver/daemons/scripts/hs_scrapers.py +264 -0
  197. pandaserver/daemons/scripts/metric_collector.py +927 -0
  198. pandaserver/daemons/scripts/panda_activeusers_query.py +80 -0
  199. pandaserver/daemons/scripts/pilotStreaming.py +109 -0
  200. pandaserver/daemons/scripts/process_workflow_files_daemon.py +166 -0
  201. pandaserver/daemons/scripts/recover_lost_files_daemon.py +177 -0
  202. pandaserver/daemons/scripts/task_evaluator.py +405 -0
  203. pandaserver/daemons/scripts/tmpwatch.py +70 -0
  204. pandaserver/daemons/scripts/worker_synchronization.py +97 -0
  205. pandaserver/daemons/utils.py +753 -0
  206. pandaserver/dataservice/DataServiceUtils.py +323 -0
  207. pandaserver/dataservice/ErrorCode.py +25 -0
  208. pandaserver/dataservice/RecoverLostFilesCore.py +322 -0
  209. pandaserver/dataservice/__init__.py +0 -0
  210. pandaserver/dataservice/activator.py +79 -0
  211. pandaserver/dataservice/adder_atlas_plugin.py +1106 -0
  212. pandaserver/dataservice/adder_dummy_plugin.py +31 -0
  213. pandaserver/dataservice/adder_gen.py +954 -0
  214. pandaserver/dataservice/adder_plugin_base.py +27 -0
  215. pandaserver/dataservice/adder_result.py +75 -0
  216. pandaserver/dataservice/adder_simple_plugin.py +160 -0
  217. pandaserver/dataservice/closer.py +247 -0
  218. pandaserver/dataservice/closer_atlas_plugin.py +90 -0
  219. pandaserver/dataservice/ddm.py +1381 -0
  220. pandaserver/dataservice/ddm_handler.py +95 -0
  221. pandaserver/dataservice/dyn_data_distributer.py +824 -0
  222. pandaserver/dataservice/event_lookup_client_ei.py +77 -0
  223. pandaserver/dataservice/event_picker.py +268 -0
  224. pandaserver/dataservice/finisher.py +194 -0
  225. pandaserver/dataservice/setupper.py +225 -0
  226. pandaserver/dataservice/setupper_atlas_plugin.py +1851 -0
  227. pandaserver/dataservice/setupper_dummy_plugin.py +47 -0
  228. pandaserver/dataservice/setupper_plugin_base.py +67 -0
  229. pandaserver/jobdispatcher/DispatcherUtils.py +35 -0
  230. pandaserver/jobdispatcher/ErrorCode.py +19 -0
  231. pandaserver/jobdispatcher/JobDispatcher.py +1625 -0
  232. pandaserver/jobdispatcher/Protocol.py +443 -0
  233. pandaserver/jobdispatcher/Watcher.py +186 -0
  234. pandaserver/jobdispatcher/__init__.py +0 -0
  235. pandaserver/pandamcp/__init__.py +0 -0
  236. pandaserver/pandamcp/mcp_main.py +56 -0
  237. pandaserver/pandamcp/mcp_test_client.py +95 -0
  238. pandaserver/pandamcp/mcp_utils.py +74 -0
  239. pandaserver/proxycache/__init__.py +0 -0
  240. pandaserver/proxycache/panda_proxy_cache.py +240 -0
  241. pandaserver/proxycache/token_cache.py +141 -0
  242. pandaserver/server/.gacl +6 -0
  243. pandaserver/server/panda.py +539 -0
  244. pandaserver/srvcore/CoreUtils.py +572 -0
  245. pandaserver/srvcore/MailUtils.py +106 -0
  246. pandaserver/srvcore/__init__.py +0 -0
  247. pandaserver/srvcore/allowed_methods.py +100 -0
  248. pandaserver/srvcore/oidc_utils.py +152 -0
  249. pandaserver/srvcore/panda_request.py +196 -0
  250. pandaserver/srvcore/srv_msg_utils.py +42 -0
  251. pandaserver/taskbuffer/ConBridge.py +513 -0
  252. pandaserver/taskbuffer/DBProxyPool.py +95 -0
  253. pandaserver/taskbuffer/DataCarousel.py +3053 -0
  254. pandaserver/taskbuffer/DatasetSpec.py +137 -0
  255. pandaserver/taskbuffer/DdmSpec.py +201 -0
  256. pandaserver/taskbuffer/ErrorCode.py +87 -0
  257. pandaserver/taskbuffer/EventServiceUtils.py +396 -0
  258. pandaserver/taskbuffer/FileSpec.py +290 -0
  259. pandaserver/taskbuffer/GlobalShares.py +244 -0
  260. pandaserver/taskbuffer/HarvesterMetricsSpec.py +92 -0
  261. pandaserver/taskbuffer/Initializer.py +82 -0
  262. pandaserver/taskbuffer/InputChunk.py +1080 -0
  263. pandaserver/taskbuffer/JediCacheSpec.py +57 -0
  264. pandaserver/taskbuffer/JediDatasetSpec.py +588 -0
  265. pandaserver/taskbuffer/JediFileSpec.py +242 -0
  266. pandaserver/taskbuffer/JediTaskSpec.py +1687 -0
  267. pandaserver/taskbuffer/JobSpec.py +1006 -0
  268. pandaserver/taskbuffer/JobUtils.py +232 -0
  269. pandaserver/taskbuffer/NucleusSpec.py +116 -0
  270. pandaserver/taskbuffer/OraDBProxy.py +174 -0
  271. pandaserver/taskbuffer/PanDAMsgProcessor.py +8 -0
  272. pandaserver/taskbuffer/PandaDBSchemaInfo.py +18 -0
  273. pandaserver/taskbuffer/ParseJobXML.py +350 -0
  274. pandaserver/taskbuffer/PickleFileSpec.py +18 -0
  275. pandaserver/taskbuffer/PickleJobSpec.py +25 -0
  276. pandaserver/taskbuffer/PrioUtil.py +40 -0
  277. pandaserver/taskbuffer/ProcessGroups.py +111 -0
  278. pandaserver/taskbuffer/ResourceSpec.py +175 -0
  279. pandaserver/taskbuffer/SQLDumper.py +37 -0
  280. pandaserver/taskbuffer/SQLManager.py +60 -0
  281. pandaserver/taskbuffer/SiteSpec.py +304 -0
  282. pandaserver/taskbuffer/SupErrors.py +10 -0
  283. pandaserver/taskbuffer/TaskBuffer.py +2882 -0
  284. pandaserver/taskbuffer/TaskBufferInterface.py +163 -0
  285. pandaserver/taskbuffer/Utils.py +848 -0
  286. pandaserver/taskbuffer/WorkQueue.py +227 -0
  287. pandaserver/taskbuffer/WorkQueueMapper.py +203 -0
  288. pandaserver/taskbuffer/WorkerSpec.py +143 -0
  289. pandaserver/taskbuffer/WrappedCursor.py +487 -0
  290. pandaserver/taskbuffer/WrappedPickle.py +88 -0
  291. pandaserver/taskbuffer/WrappedPostgresConn.py +24 -0
  292. pandaserver/taskbuffer/__init__.py +0 -0
  293. pandaserver/taskbuffer/db_proxy_mods/OraDBProxy_structure.png +0 -0
  294. pandaserver/taskbuffer/db_proxy_mods/__init__.py +7 -0
  295. pandaserver/taskbuffer/db_proxy_mods/base_module.py +841 -0
  296. pandaserver/taskbuffer/db_proxy_mods/data_carousel_module.py +772 -0
  297. pandaserver/taskbuffer/db_proxy_mods/entity_module.py +3804 -0
  298. pandaserver/taskbuffer/db_proxy_mods/job_complex_module.py +5661 -0
  299. pandaserver/taskbuffer/db_proxy_mods/job_standalone_module.py +2640 -0
  300. pandaserver/taskbuffer/db_proxy_mods/metrics_module.py +874 -0
  301. pandaserver/taskbuffer/db_proxy_mods/misc_standalone_module.py +4272 -0
  302. pandaserver/taskbuffer/db_proxy_mods/task_complex_module.py +6172 -0
  303. pandaserver/taskbuffer/db_proxy_mods/task_event_module.py +4953 -0
  304. pandaserver/taskbuffer/db_proxy_mods/task_standalone_module.py +4999 -0
  305. pandaserver/taskbuffer/db_proxy_mods/task_utils_module.py +2063 -0
  306. pandaserver/taskbuffer/db_proxy_mods/worker_module.py +1944 -0
  307. pandaserver/taskbuffer/db_proxy_mods/workflow_module.py +832 -0
  308. pandaserver/taskbuffer/retryModule.py +552 -0
  309. pandaserver/taskbuffer/task_split_rules.py +308 -0
  310. pandaserver/taskbuffer/workflow_processor.py +249 -0
  311. pandaserver/taskbuffer/wrapped_oracle_conn.py +18 -0
  312. pandaserver/test/SchemaChecker.py +40 -0
  313. pandaserver/test/__init__.py +0 -0
  314. pandaserver/test/banUser.py +43 -0
  315. pandaserver/test/boostPrio.py +19 -0
  316. pandaserver/test/boostUser.py +35 -0
  317. pandaserver/test/callbackDDM.py +11 -0
  318. pandaserver/test/daod_on_demand.py +95 -0
  319. pandaserver/test/finishJob.py +184 -0
  320. pandaserver/test/finishTaskJEDI.py +11 -0
  321. pandaserver/test/getJobs.py +53 -0
  322. pandaserver/test/killJob.py +79 -0
  323. pandaserver/test/killJobLowPrio.py +99 -0
  324. pandaserver/test/killJobsInTask.py +56 -0
  325. pandaserver/test/killTask.py +80 -0
  326. pandaserver/test/killTaskJEDI.py +11 -0
  327. pandaserver/test/killUser.py +83 -0
  328. pandaserver/test/lsst/README.txt +7 -0
  329. pandaserver/test/lsst/lsstSubmit.py +139 -0
  330. pandaserver/test/lsst/lsstSubmitMERGEtest.py +141 -0
  331. pandaserver/test/lsst/lsstSubmitPhosim332.py +53 -0
  332. pandaserver/test/lsst/prepare-client-tarball-from-bigpanda-server.sh +41 -0
  333. pandaserver/test/reassignJobs.py +17 -0
  334. pandaserver/test/reassignSite.py +82 -0
  335. pandaserver/test/reassignTask.py +117 -0
  336. pandaserver/test/reassignWaiting.py +39 -0
  337. pandaserver/test/recoverLostFiles.py +7 -0
  338. pandaserver/test/reloadInputDS.py +51 -0
  339. pandaserver/test/sendCommandToJob.py +26 -0
  340. pandaserver/test/setDebugMode.py +38 -0
  341. pandaserver/test/setPriority.py +28 -0
  342. pandaserver/test/testEvgen.py +60 -0
  343. pandaserver/test/testEvgen17.py +58 -0
  344. pandaserver/test/testG4sim.py +81 -0
  345. pandaserver/test/testG4sim17.py +90 -0
  346. pandaserver/test/testGlobalShares.py +131 -0
  347. pandaserver/test/testReco.py +103 -0
  348. pandaserver/test/testSimulReco14.py +98 -0
  349. pandaserver/test/testSiteMap.py +26 -0
  350. pandaserver/test/testUpdateWorkerPilotStatus.py +9 -0
  351. pandaserver/userinterface/Client.py +1686 -0
  352. pandaserver/userinterface/UserIF.py +1799 -0
  353. pandaserver/userinterface/__init__.py +0 -0
  354. pandaserver/workflow/__init__.py +0 -0
  355. pandaserver/workflow/data_handler_plugins/base_data_handler.py +48 -0
  356. pandaserver/workflow/data_handler_plugins/ddm_collection_data_handler.py +100 -0
  357. pandaserver/workflow/data_handler_plugins/panda_task_data_handler.py +140 -0
  358. pandaserver/workflow/pcwl_test.py +122 -0
  359. pandaserver/workflow/pcwl_utils.py +384 -0
  360. pandaserver/workflow/psnakemake_container.json +68 -0
  361. pandaserver/workflow/psnakemake_task.json +62 -0
  362. pandaserver/workflow/psnakemake_test.py +60 -0
  363. pandaserver/workflow/snakeparser/__init__.py +3 -0
  364. pandaserver/workflow/snakeparser/extensions.py +74 -0
  365. pandaserver/workflow/snakeparser/log.py +53 -0
  366. pandaserver/workflow/snakeparser/names.py +3 -0
  367. pandaserver/workflow/snakeparser/parser.py +332 -0
  368. pandaserver/workflow/snakeparser/utils.py +29 -0
  369. pandaserver/workflow/step_handler_plugins/base_step_handler.py +85 -0
  370. pandaserver/workflow/step_handler_plugins/panda_task_step_handler.py +280 -0
  371. pandaserver/workflow/workflow_base.py +531 -0
  372. pandaserver/workflow/workflow_core.py +1974 -0
  373. pandaserver/workflow/workflow_core_smoketest.py +388 -0
  374. pandaserver/workflow/workflow_parser.py +222 -0
  375. pandaserver/workflow/workflow_utils.py +1047 -0
@@ -0,0 +1,996 @@
1
+ import copy
2
+ import datetime
3
+ import re
4
+ import sys
5
+ import uuid
6
+
7
+ from pandacommon.pandautils.PandaUtils import naive_utcnow
8
+
9
+ from pandajedi.jedicore import Interaction, JediException
10
+ from pandaserver.taskbuffer import EventServiceUtils, task_split_rules
11
+ from pandaserver.taskbuffer.JediDatasetSpec import JediDatasetSpec
12
+ from pandaserver.taskbuffer.JediFileSpec import JediFileSpec
13
+ from pandaserver.taskbuffer.JediTaskSpec import JediTaskSpec
14
+
15
+ from . import RefinerUtils
16
+
17
+ try:
18
+ import idds.common.constants
19
+ import idds.common.utils
20
+ from idds.client.client import Client as iDDS_Client
21
+ except ImportError:
22
+ pass
23
+
24
+
25
+ # base class for task refine
26
+ class TaskRefinerBase(object):
27
+ # constructor
28
+ def __init__(self, taskBufferIF, ddmIF):
29
+ self.ddmIF = ddmIF
30
+ self.taskBufferIF = taskBufferIF
31
+ self.initializeRefiner(None)
32
+ self.refresh()
33
+
34
+ # refresh
35
+ def refresh(self):
36
+ self.siteMapper = self.taskBufferIF.get_site_mapper()
37
+
38
+ # initialize
39
+ def initializeRefiner(self, tmpLog):
40
+ self.taskSpec = None
41
+ self.inMasterDatasetSpec = []
42
+ self.inSecDatasetSpecList = []
43
+ self.outDatasetSpecList = []
44
+ self.outputTemplateMap = {}
45
+ self.jobParamsTemplate = None
46
+ self.cloudName = None
47
+ self.siteName = None
48
+ self.tmpLog = tmpLog
49
+ self.updatedTaskParams = None
50
+ self.unmergeMasterDatasetSpec = {}
51
+ self.unmergeDatasetSpecMap = {}
52
+ self.oldTaskStatus = None
53
+ self.unknownDatasetList = []
54
+
55
+ # set jobParamsTemplate
56
+ def setJobParamsTemplate(self, jobParamsTemplate):
57
+ self.jobParamsTemplate = jobParamsTemplate
58
+
59
+ # create a unique identifier of the payload based on the task parameters
60
+ def create_payload_identifier(self, task_param_map: dict) -> str:
61
+ """
62
+ Create a unique identifier of the payload based on the task parameters
63
+ :param task_param_map: dictionary of task parameters
64
+ :return: identifier string
65
+ """
66
+ # remove placeholders from job parameter template
67
+ if self.jobParamsTemplate:
68
+ job_params = re.sub(r"\$\{.*?\}", "", self.jobParamsTemplate)
69
+ else:
70
+ job_params = ""
71
+ # create a base string for the payload identifier
72
+ base_str = "+".join(
73
+ [
74
+ str(self.taskSpec.transUses),
75
+ str(self.taskSpec.transHome),
76
+ str(self.taskSpec.transPath),
77
+ job_params,
78
+ str(RefinerUtils.get_sandbox_name(task_param_map)),
79
+ ]
80
+ )
81
+ # create a unique identifier of the payload based on the task parameters
82
+ return uuid.uuid5(uuid.NAMESPACE_DNS, base_str).hex
83
+
84
+ # extract common parameters
85
+ def extractCommon(self, jediTaskID, taskParamMap, workQueueMapper, splitRule):
86
+ # remove irrelevant
87
+ if "maxAttempt" in taskParamMap and not taskParamMap["maxAttempt"]:
88
+ del taskParamMap["maxAttempt"]
89
+ # make task spec
90
+ taskSpec = JediTaskSpec()
91
+ taskSpec.jediTaskID = jediTaskID
92
+ taskSpec.attemptNr = 0
93
+ taskSpec.taskName = taskParamMap["taskName"]
94
+ taskSpec.userName = taskParamMap["userName"]
95
+ taskSpec.vo = taskParamMap["vo"]
96
+ taskSpec.framework = taskParamMap.get("framework", None)
97
+ taskSpec.prodSourceLabel = taskParamMap["prodSourceLabel"]
98
+ taskSpec.taskPriority = taskParamMap["taskPriority"]
99
+ if taskSpec.taskPriority is None:
100
+ taskSpec.taskPriority = 0
101
+ if "currentPriority" in taskParamMap:
102
+ taskSpec.currentPriority = taskParamMap["currentPriority"]
103
+ else:
104
+ taskSpec.currentPriority = taskSpec.taskPriority
105
+ taskSpec.architecture = taskParamMap["architecture"]
106
+ taskSpec.reformat_architecture()
107
+ taskSpec.transUses = taskParamMap["transUses"]
108
+ taskSpec.transHome = taskParamMap["transHome"]
109
+ if "transPath" in taskParamMap:
110
+ taskSpec.transPath = taskParamMap["transPath"]
111
+ taskSpec.processingType = taskParamMap["processingType"]
112
+ taskSpec.taskType = taskParamMap["taskType"]
113
+ taskSpec.splitRule = splitRule
114
+ taskSpec.startTime = naive_utcnow()
115
+ if "workingGroup" in taskParamMap:
116
+ taskSpec.workingGroup = taskParamMap["workingGroup"]
117
+ if "countryGroup" in taskParamMap:
118
+ taskSpec.countryGroup = taskParamMap["countryGroup"]
119
+ if "ticketID" in taskParamMap:
120
+ taskSpec.ticketID = taskParamMap["ticketID"]
121
+ if "ticketSystemType" in taskParamMap:
122
+ taskSpec.ticketSystemType = taskParamMap["ticketSystemType"]
123
+ if "reqID" in taskParamMap:
124
+ taskSpec.reqID = taskParamMap["reqID"]
125
+ else:
126
+ taskSpec.reqID = jediTaskID
127
+ if "coreCount" in taskParamMap:
128
+ taskSpec.coreCount = taskParamMap["coreCount"]
129
+ else:
130
+ taskSpec.coreCount = 1
131
+ if "walltime" in taskParamMap:
132
+ taskSpec.walltime = taskParamMap["walltime"]
133
+ else:
134
+ taskSpec.walltime = 0
135
+ if "walltimeUnit" not in taskParamMap:
136
+ # force to set NULL so that retried tasks get data from scouts again
137
+ taskSpec.forceUpdate("walltimeUnit")
138
+ if "outDiskCount" in taskParamMap:
139
+ taskSpec.outDiskCount = taskParamMap["outDiskCount"]
140
+ else:
141
+ taskSpec.outDiskCount = 0
142
+ if "outDiskUnit" in taskParamMap:
143
+ taskSpec.outDiskUnit = taskParamMap["outDiskUnit"]
144
+ if "workDiskCount" in taskParamMap:
145
+ taskSpec.workDiskCount = taskParamMap["workDiskCount"]
146
+ else:
147
+ taskSpec.workDiskCount = 0
148
+ if "workDiskUnit" in taskParamMap:
149
+ taskSpec.workDiskUnit = taskParamMap["workDiskUnit"]
150
+ if "ramCount" in taskParamMap:
151
+ taskSpec.ramCount = taskParamMap["ramCount"]
152
+ else:
153
+ taskSpec.ramCount = 0
154
+ if "ramUnit" in taskParamMap:
155
+ taskSpec.ramUnit = taskParamMap["ramUnit"]
156
+ elif "ramCountUnit" in taskParamMap:
157
+ taskSpec.ramUnit = taskParamMap["ramCountUnit"]
158
+ if "baseRamCount" in taskParamMap:
159
+ taskSpec.baseRamCount = taskParamMap["baseRamCount"]
160
+ else:
161
+ taskSpec.baseRamCount = 0
162
+ # IO
163
+ if "ioIntensity" in taskParamMap:
164
+ taskSpec.ioIntensity = taskParamMap["ioIntensity"]
165
+ if "ioIntensityUnit" in taskParamMap:
166
+ taskSpec.ioIntensityUnit = taskParamMap["ioIntensityUnit"]
167
+ # HS06 stuff
168
+ if "cpuTimeUnit" in taskParamMap:
169
+ taskSpec.cpuTimeUnit = taskParamMap["cpuTimeUnit"]
170
+ if "cpuTime" in taskParamMap:
171
+ taskSpec.cpuTime = taskParamMap["cpuTime"]
172
+ if "cpuEfficiency" in taskParamMap:
173
+ taskSpec.cpuEfficiency = taskParamMap["cpuEfficiency"]
174
+ else:
175
+ # 90% of cpu efficiency by default
176
+ taskSpec.cpuEfficiency = 90
177
+ if "baseWalltime" in taskParamMap:
178
+ taskSpec.baseWalltime = taskParamMap["baseWalltime"]
179
+ else:
180
+ # 10min of offset by default
181
+ taskSpec.baseWalltime = 10 * 60
182
+ # for merge
183
+ if "mergeRamCount" in taskParamMap:
184
+ taskSpec.mergeRamCount = taskParamMap["mergeRamCount"]
185
+ if "mergeCoreCount" in taskParamMap:
186
+ taskSpec.mergeCoreCount = taskParamMap["mergeCoreCount"]
187
+ # scout
188
+ if "skipScout" not in taskParamMap and not taskSpec.isPostScout():
189
+ taskSpec.setUseScout(True)
190
+ # cloud
191
+ if "cloud" in taskParamMap:
192
+ self.cloudName = taskParamMap["cloud"]
193
+ taskSpec.cloud = self.cloudName
194
+ else:
195
+ # set dummy to force update
196
+ taskSpec.cloud = "dummy"
197
+ taskSpec.cloud = None
198
+ # site
199
+ if "site" in taskParamMap:
200
+ self.siteName = taskParamMap["site"]
201
+ taskSpec.site = self.siteName
202
+ else:
203
+ # set dummy to force update
204
+ taskSpec.site = "dummy"
205
+ taskSpec.site = None
206
+ # nucleus
207
+ if "nucleus" in taskParamMap:
208
+ taskSpec.nucleus = taskParamMap["nucleus"]
209
+ # preset some parameters for job cloning
210
+ if "useJobCloning" in taskParamMap:
211
+ # set implicit parameters
212
+ if "nEventsPerWorker" not in taskParamMap:
213
+ taskParamMap["nEventsPerWorker"] = 1
214
+ if "nSitesPerJob" not in taskParamMap:
215
+ taskParamMap["nSitesPerJob"] = 2
216
+ if "nEsConsumers" not in taskParamMap:
217
+ taskParamMap["nEsConsumers"] = taskParamMap["nSitesPerJob"]
218
+ # minimum granularity
219
+ if "minGranularity" in taskParamMap:
220
+ taskParamMap["nEventsPerRange"] = taskParamMap["minGranularity"]
221
+ # event service flag
222
+ if "useJobCloning" in taskParamMap:
223
+ taskSpec.eventService = EventServiceUtils.TASK_JOB_CLONING
224
+ elif "nEventsPerWorker" in taskParamMap:
225
+ taskSpec.eventService = EventServiceUtils.TASK_EVENT_SERVICE
226
+ elif "fineGrainedProc" in taskParamMap:
227
+ taskSpec.eventService = EventServiceUtils.TASK_FINE_GRAINED
228
+ else:
229
+ taskSpec.eventService = EventServiceUtils.TASK_NORMAL
230
+ # OS
231
+ if "osInfo" in taskParamMap:
232
+ taskSpec.termCondition = taskParamMap["osInfo"]
233
+ # ttcr: requested time to completion
234
+ if "ttcrTimestamp" in taskParamMap:
235
+ try:
236
+ # get rid of the +00:00 timezone string and parse the timestamp
237
+ taskSpec.ttcRequested = datetime.datetime.strptime(taskParamMap["ttcrTimestamp"].split("+")[0], "%Y-%m-%d %H:%M:%S.%f")
238
+ except (IndexError, ValueError):
239
+ pass
240
+ # goal
241
+ if "goal" in taskParamMap:
242
+ try:
243
+ taskSpec.goal = int(float(taskParamMap["goal"]) * 10)
244
+ if taskSpec.goal > 1000:
245
+ taskSpec.goal = None
246
+ except Exception:
247
+ pass
248
+ # campaign
249
+ if "campaign" in taskParamMap:
250
+ taskSpec.campaign = taskParamMap["campaign"]
251
+ # image name
252
+ if "container_name" in taskParamMap:
253
+ taskSpec.container_name = taskParamMap["container_name"]
254
+ self.taskSpec = taskSpec
255
+ # set split rule
256
+ if "nFilesPerJob" not in taskParamMap:
257
+ if "tgtNumEventsPerJob" in taskParamMap:
258
+ # set nEventsPerJob not to respect file boundaries when nFilesPerJob is not used
259
+ self.setSplitRule(None, taskParamMap["tgtNumEventsPerJob"], JediTaskSpec.splitRuleToken["nEventsPerJob"])
260
+ elif (
261
+ "nEventsPerInputFile" in taskParamMap
262
+ and "nEventsPerJob" in taskParamMap
263
+ and taskParamMap["nEventsPerJob"] >= taskParamMap["nEventsPerInputFile"]
264
+ ):
265
+ # set nFilesPerJob if nEventsPerJob and nEventsPerInputFile are set
266
+ nFilesPerJob = taskParamMap["nEventsPerJob"] // taskParamMap["nEventsPerInputFile"]
267
+ self.setSplitRule(None, nFilesPerJob, JediTaskSpec.splitRuleToken["nFilesPerJob"])
268
+ else:
269
+ self.setSplitRule(taskParamMap, "nFilesPerJob", JediTaskSpec.splitRuleToken["nFilesPerJob"])
270
+ self.setSplitRule(taskParamMap, "nEventsPerJob", JediTaskSpec.splitRuleToken["nEventsPerJob"])
271
+ self.setSplitRule(taskParamMap, "nGBPerJob", JediTaskSpec.splitRuleToken["nGBPerJob"])
272
+ self.setSplitRule(taskParamMap, "nMaxFilesPerJob", JediTaskSpec.splitRuleToken["nMaxFilesPerJob"])
273
+ self.setSplitRule(taskParamMap, "maxEventsPerJob", JediTaskSpec.splitRuleToken["maxEventsPerJob"])
274
+ self.setSplitRule(taskParamMap, "nEventsPerWorker", JediTaskSpec.splitRuleToken["nEventsPerWorker"])
275
+ self.setSplitRule(taskParamMap, "nEventsPerInputFile", JediTaskSpec.splitRuleToken["nEventsPerInput"])
276
+ self.setSplitRule(taskParamMap, "disableAutoRetry", JediTaskSpec.splitRuleToken["disableAutoRetry"])
277
+ self.setSplitRule(taskParamMap, "nEsConsumers", JediTaskSpec.splitRuleToken["nEsConsumers"])
278
+ self.setSplitRule(taskParamMap, "waitInput", JediTaskSpec.splitRuleToken["waitInput"])
279
+ self.setSplitRule(taskParamMap, "addNthFieldToLFN", JediTaskSpec.splitRuleToken["addNthFieldToLFN"])
280
+ self.setSplitRule(taskParamMap, "scoutSuccessRate", JediTaskSpec.splitRuleToken["scoutSuccessRate"])
281
+ self.setSplitRule(taskParamMap, "t1Weight", JediTaskSpec.splitRuleToken["t1Weight"])
282
+ self.setSplitRule(taskParamMap, "maxAttemptES", JediTaskSpec.splitRuleToken["maxAttemptES"])
283
+ self.setSplitRule(taskParamMap, "maxAttemptEsJob", JediTaskSpec.splitRuleToken["maxAttemptEsJob"])
284
+ self.setSplitRule(taskParamMap, "nSitesPerJob", JediTaskSpec.splitRuleToken["nSitesPerJob"])
285
+ self.setSplitRule(taskParamMap, "nEventsPerMergeJob", JediTaskSpec.splitRuleToken["nEventsPerMergeJob"])
286
+ self.setSplitRule(taskParamMap, "nFilesPerMergeJob", JediTaskSpec.splitRuleToken["nFilesPerMergeJob"])
287
+ self.setSplitRule(taskParamMap, "nGBPerMergeJob", JediTaskSpec.splitRuleToken["nGBPerMergeJob"])
288
+ self.setSplitRule(taskParamMap, "nMaxFilesPerMergeJob", JediTaskSpec.splitRuleToken["nMaxFilesPerMergeJob"])
289
+ self.setSplitRule(taskParamMap, "maxWalltime", JediTaskSpec.splitRuleToken["maxWalltime"])
290
+ self.setSplitRule(taskParamMap, "tgtMaxOutputForNG", JediTaskSpec.splitRuleToken["tgtMaxOutputForNG"])
291
+ self.setSplitRule(taskParamMap, "maxNumJobs", JediTaskSpec.splitRuleToken["maxNumJobs"])
292
+ self.setSplitRule(taskParamMap, "totNumJobs", JediTaskSpec.splitRuleToken["totNumJobs"])
293
+ self.setSplitRule(taskParamMap, "nChunksToWait", JediTaskSpec.splitRuleToken["nChunksToWait"])
294
+ self.setSplitRule(taskParamMap, "retryRamOffset", JediTaskSpec.splitRuleToken["retryRamOffset"])
295
+ self.setSplitRule(taskParamMap, "retryRamStep", JediTaskSpec.splitRuleToken["retryRamStep"])
296
+ self.setSplitRule(taskParamMap, "retryRamMax", JediTaskSpec.splitRuleToken["retryRamMax"])
297
+ if "forceStaged" in taskParamMap:
298
+ taskParamMap["useLocalIO"] = taskParamMap["forceStaged"]
299
+ if "useLocalIO" in taskParamMap:
300
+ if taskParamMap["useLocalIO"]:
301
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["useLocalIO"])
302
+ else:
303
+ self.setSplitRule(None, 0, JediTaskSpec.splitRuleToken["useLocalIO"])
304
+ if "nJumboJobs" in taskParamMap:
305
+ self.setSplitRule(taskParamMap, "nJumboJobs", JediTaskSpec.splitRuleToken["nJumboJobs"])
306
+ taskSpec.useJumbo = JediTaskSpec.enum_useJumbo["waiting"]
307
+ if "maxJumboPerSite" in taskParamMap:
308
+ self.setSplitRule(taskParamMap, "maxJumboPerSite", JediTaskSpec.splitRuleToken["maxJumboPerSite"])
309
+ if "minCpuEfficiency" in taskParamMap:
310
+ self.setSplitRule(taskParamMap, "minCpuEfficiency", JediTaskSpec.splitRuleToken["minCpuEfficiency"])
311
+ if "loadXML" in taskParamMap:
312
+ self.setSplitRule(None, 3, JediTaskSpec.splitRuleToken["loadXML"])
313
+ self.setSplitRule(None, 4, JediTaskSpec.splitRuleToken["groupBoundaryID"])
314
+ if "pfnList" in taskParamMap:
315
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["pfnList"])
316
+ if "noWaitParent" in taskParamMap and taskParamMap["noWaitParent"] is True:
317
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["noWaitParent"])
318
+ if "respectLB" in taskParamMap:
319
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["respectLB"])
320
+ if "releasePerLB" in taskParamMap:
321
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["releasePerLB"])
322
+ if "orderByLB" in taskParamMap:
323
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["orderByLB"])
324
+ if "respectSplitRule" in taskParamMap:
325
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["respectSplitRule"])
326
+ if "reuseSecOnDemand" in taskParamMap:
327
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["reuseSecOnDemand"])
328
+ if "ddmBackEnd" in taskParamMap:
329
+ self.taskSpec.setDdmBackEnd(taskParamMap["ddmBackEnd"])
330
+ if "disableReassign" in taskParamMap:
331
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["disableReassign"])
332
+ if "allowPartialFinish" in taskParamMap:
333
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["allowPartialFinish"])
334
+ if "useExhausted" in taskParamMap:
335
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["useExhausted"])
336
+ if "useRealNumEvents" in taskParamMap:
337
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["useRealNumEvents"])
338
+ if "ipConnectivity" in taskParamMap:
339
+ self.taskSpec.setIpConnectivity(taskParamMap["ipConnectivity"])
340
+ if "altStageOut" in taskParamMap:
341
+ self.taskSpec.setAltStageOut(taskParamMap["altStageOut"])
342
+ if "allowInputLAN" in taskParamMap:
343
+ self.taskSpec.setAllowInputLAN(taskParamMap["allowInputLAN"])
344
+ if "runUntilClosed" in taskParamMap:
345
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["runUntilClosed"])
346
+ if "stayOutputOnSite" in taskParamMap:
347
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["stayOutputOnSite"])
348
+ if "useJobCloning" in taskParamMap:
349
+ scValue = EventServiceUtils.getJobCloningValue(taskParamMap["useJobCloning"])
350
+ self.setSplitRule(None, scValue, JediTaskSpec.splitRuleToken["useJobCloning"])
351
+ if "failWhenGoalUnreached" in taskParamMap and taskParamMap["failWhenGoalUnreached"] is True:
352
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["failGoalUnreached"])
353
+ if "switchEStoNormal" in taskParamMap:
354
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["switchEStoNormal"])
355
+ if "nEventsPerRange" in taskParamMap:
356
+ self.setSplitRule(taskParamMap, "nEventsPerRange", JediTaskSpec.splitRuleToken["dynamicNumEvents"])
357
+ if "allowInputWAN" in taskParamMap and taskParamMap["allowInputWAN"] is True:
358
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["allowInputWAN"])
359
+ if "putLogToOS" in taskParamMap and taskParamMap["putLogToOS"] is True:
360
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["putLogToOS"])
361
+ if "mergeEsOnOS" in taskParamMap and taskParamMap["mergeEsOnOS"] is True:
362
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["mergeEsOnOS"])
363
+ if "writeInputToFile" in taskParamMap and taskParamMap["writeInputToFile"] is True:
364
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["writeInputToFile"])
365
+ if "useFileAsSourceLFN" in taskParamMap and taskParamMap["useFileAsSourceLFN"] is True:
366
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["useFileAsSourceLFN"])
367
+ if "ignoreMissingInDS" in taskParamMap and taskParamMap["ignoreMissingInDS"] is True:
368
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["ignoreMissingInDS"])
369
+ if "noExecStrCnv" in taskParamMap and taskParamMap["noExecStrCnv"] is True:
370
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["noExecStrCnv"])
371
+ if "inFilePosEvtNum" in taskParamMap and taskParamMap["inFilePosEvtNum"] is True:
372
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["inFilePosEvtNum"])
373
+ if self.taskSpec.useEventService() and not taskSpec.useJobCloning():
374
+ if "registerEsFiles" in taskParamMap and taskParamMap["registerEsFiles"] is True:
375
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["registerEsFiles"])
376
+ if "disableAutoFinish" in taskParamMap and taskParamMap["disableAutoFinish"] is True:
377
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["disableAutoFinish"])
378
+ if "resurrectConsumers" in taskParamMap and taskParamMap["resurrectConsumers"] is True:
379
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["resurrectConsumers"])
380
+ if "usePrefetcher" in taskParamMap and taskParamMap["usePrefetcher"] is True:
381
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["usePrefetcher"])
382
+ if "notDiscardEvents" in taskParamMap and taskParamMap["notDiscardEvents"] is True:
383
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["notDiscardEvents"])
384
+ if "decAttOnFailedES" in taskParamMap and taskParamMap["decAttOnFailedES"] is True:
385
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["decAttOnFailedES"])
386
+ if "useZipToPin" in taskParamMap and taskParamMap["useZipToPin"] is True:
387
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["useZipToPin"])
388
+ if "osMatching" in taskParamMap and taskParamMap["osMatching"] is True:
389
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["osMatching"])
390
+ if "multiStepExec" in taskParamMap:
391
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["multiStepExec"])
392
+ if "onlyTagsForFC" in taskParamMap:
393
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["onlyTagsForFC"])
394
+ if "segmentedWork" in taskParamMap and "segmentSpecs" in taskParamMap:
395
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["segmentedWork"])
396
+ if "avoidVP" in taskParamMap:
397
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["avoidVP"])
398
+ if "inputPreStaging" in taskParamMap and taskParamMap["inputPreStaging"] is True:
399
+ self.setSplitRule(None, JediTaskSpec.enum_inputPreStaging["use"], JediTaskSpec.splitRuleToken["inputPreStaging"])
400
+ if "hpoWorkflow" in taskParamMap and taskParamMap["hpoWorkflow"] is True and "hpoRequestData" in taskParamMap:
401
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["hpoWorkflow"])
402
+ if "noLoopingCheck" in taskParamMap and taskParamMap["noLoopingCheck"]:
403
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["noLoopingCheck"])
404
+ if "encJobParams" in taskParamMap and taskParamMap["encJobParams"]:
405
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["encJobParams"])
406
+ if "useSecrets" in taskParamMap and taskParamMap["useSecrets"]:
407
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["useSecrets"])
408
+ if "debugMode" in taskParamMap and taskParamMap["debugMode"]:
409
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["debugMode"])
410
+ if "pushStatusChanges" in taskParamMap and taskParamMap["pushStatusChanges"]:
411
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["pushStatusChanges"])
412
+ if "maxCoreCount" in taskParamMap:
413
+ self.setSplitRule(taskParamMap, "maxCoreCount", JediTaskSpec.splitRuleToken["maxCoreCount"])
414
+ if "cloudAsVO" in taskParamMap:
415
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["cloudAsVO"])
416
+ if "pushJob" in taskParamMap and taskParamMap["pushJob"]:
417
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["pushJob"])
418
+ if "fineGrainedProc" in taskParamMap and taskParamMap["fineGrainedProc"]:
419
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["fineGrainedProc"])
420
+ if "onSiteMerging" in taskParamMap and taskParamMap["onSiteMerging"]:
421
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["onSiteMerging"])
422
+ if "fullChain" in taskParamMap:
423
+ self.taskSpec.set_full_chain(taskParamMap["fullChain"])
424
+ if "orderInputBy" in taskParamMap:
425
+ self.taskSpec.set_order_input_by(taskParamMap["orderInputBy"])
426
+ if "intermediateTask" in taskParamMap:
427
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["intermediateTask"])
428
+ if "allowEmptyInput" in taskParamMap:
429
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["allowEmptyInput"])
430
+ if "messageDriven" in taskParamMap and taskParamMap["messageDriven"]:
431
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["messageDriven"])
432
+ if "allowIncompleteInDS" in taskParamMap and taskParamMap["allowIncompleteInDS"]:
433
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["allowIncompleteInDS"])
434
+ if "noAutoPause" in taskParamMap and taskParamMap["noAutoPause"]:
435
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["noAutoPause"])
436
+ if "workflowHoldup" in taskParamMap and taskParamMap["workflowHoldup"]:
437
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["workflowHoldup"])
438
+ # work queue
439
+ workQueue = None
440
+ if "workQueueName" in taskParamMap:
441
+ # work queue is specified
442
+ workQueue = workQueueMapper.getQueueByName(taskSpec.vo, taskSpec.prodSourceLabel, taskParamMap["workQueueName"])
443
+ if workQueue is None:
444
+ # get work queue based on task attributes
445
+ workQueue, tmpStr = workQueueMapper.getQueueWithSelParams(
446
+ taskSpec.vo,
447
+ taskSpec.prodSourceLabel,
448
+ prodSourceLabel=taskSpec.prodSourceLabel,
449
+ processingType=taskSpec.processingType,
450
+ workingGroup=taskSpec.workingGroup,
451
+ coreCount=taskSpec.coreCount,
452
+ site=taskSpec.site,
453
+ eventService=taskSpec.eventService,
454
+ splitRule=taskSpec.splitRule,
455
+ campaign=taskSpec.campaign,
456
+ )
457
+ if workQueue is None:
458
+ errStr = f"workqueue is undefined for vo={taskSpec.vo} label={taskSpec.prodSourceLabel} "
459
+ errStr += "processingType={0} workingGroup={1} coreCount={2} eventService={3} ".format(
460
+ taskSpec.processingType, taskSpec.workingGroup, taskSpec.coreCount, taskSpec.eventService
461
+ )
462
+ errStr += f"splitRule={taskSpec.splitRule} campaign={taskSpec.campaign}"
463
+ raise RuntimeError(errStr)
464
+ self.taskSpec.workQueue_ID = workQueue.queue_id
465
+
466
+ # Initialize the global share
467
+ self.taskSpec.gshare = RefinerUtils.get_initial_global_share(self.taskBufferIF, self.taskSpec.jediTaskID, taskSpec, taskParamMap)
468
+
469
+ # Initialize the resource type
470
+ try:
471
+ self.taskSpec.resource_type = self.taskBufferIF.get_resource_type_task(self.taskSpec)
472
+ except Exception:
473
+ self.taskSpec.resource_type = "Undefined"
474
+
475
+ # return
476
+ return
477
+
478
+ # basic refinement procedure
479
+ def doBasicRefine(self, taskParamMap):
480
+ # get input/output/log dataset specs
481
+ nIn = 0
482
+ nOutMap = {}
483
+ if "log" not in taskParamMap:
484
+ itemList = taskParamMap["jobParameters"]
485
+ elif isinstance(taskParamMap["log"], dict):
486
+ itemList = taskParamMap["jobParameters"] + [taskParamMap["log"]]
487
+ else:
488
+ itemList = taskParamMap["jobParameters"] + taskParamMap["log"]
489
+ if "log_merge" in taskParamMap:
490
+ itemList += [taskParamMap["log_merge"]]
491
+ # pseudo input
492
+ if "noInput" in taskParamMap and taskParamMap["noInput"] is True:
493
+ tmpItem = {}
494
+ tmpItem["type"] = "template"
495
+ tmpItem["value"] = ""
496
+ tmpItem["dataset"] = "pseudo_dataset"
497
+ tmpItem["param_type"] = "pseudo_input"
498
+ itemList = [tmpItem] + itemList
499
+ # random seed
500
+ if RefinerUtils.useRandomSeed(taskParamMap):
501
+ tmpItem = {}
502
+ tmpItem["type"] = "template"
503
+ tmpItem["value"] = ""
504
+ tmpItem["dataset"] = "RNDMSEED"
505
+ tmpItem["param_type"] = "random_seed"
506
+ itemList.append(tmpItem)
507
+ # loop over all items
508
+ allDsList = []
509
+ checked_endpoints = set()
510
+ for tmpItem in itemList:
511
+ # look for datasets
512
+ if tmpItem["type"] == "template" and "dataset" in tmpItem:
513
+ # avoid duplication
514
+ if tmpItem["dataset"] not in allDsList:
515
+ allDsList.append(tmpItem["dataset"])
516
+ else:
517
+ continue
518
+ datasetSpec = JediDatasetSpec()
519
+ datasetSpec.datasetName = tmpItem["dataset"]
520
+ datasetSpec.jediTaskID = self.taskSpec.jediTaskID
521
+ datasetSpec.type = tmpItem["param_type"]
522
+ if "container" in tmpItem:
523
+ datasetSpec.containerName = tmpItem["container"]
524
+ if "token" in tmpItem:
525
+ datasetSpec.storageToken = tmpItem["token"]
526
+ if "destination" in tmpItem:
527
+ datasetSpec.destination = tmpItem["destination"]
528
+ if "attributes" in tmpItem:
529
+ datasetSpec.setDatasetAttribute(tmpItem["attributes"])
530
+ if "ratio" in tmpItem:
531
+ datasetSpec.setDatasetAttribute(f"ratio={tmpItem['ratio']}")
532
+ if "eventRatio" in tmpItem:
533
+ datasetSpec.setEventRatio(tmpItem["eventRatio"])
534
+ if "check" in tmpItem:
535
+ datasetSpec.setDatasetAttribute("cc")
536
+ if "usedup" in tmpItem:
537
+ datasetSpec.setDatasetAttribute("ud")
538
+ if "random" in tmpItem:
539
+ datasetSpec.setDatasetAttribute("rd")
540
+ if "reusable" in tmpItem:
541
+ datasetSpec.setDatasetAttribute("ru")
542
+ if "indexConsistent" in tmpItem:
543
+ datasetSpec.setDatasetAttributeWithLabel("indexConsistent")
544
+ if "mergeOnly" in tmpItem:
545
+ datasetSpec.setDatasetAttributeWithLabel("mergeOnly")
546
+ if "offset" in tmpItem:
547
+ datasetSpec.setOffset(tmpItem["offset"])
548
+ if "allowNoOutput" in tmpItem:
549
+ datasetSpec.allowNoOutput()
550
+ if "nFilesPerJob" in tmpItem:
551
+ datasetSpec.setNumFilesPerJob(tmpItem["nFilesPerJob"])
552
+ if "num_records" in tmpItem:
553
+ datasetSpec.setNumRecords(tmpItem["num_records"])
554
+ if "transient" in tmpItem:
555
+ datasetSpec.setTransient(tmpItem["transient"])
556
+ if "pseudo" in tmpItem:
557
+ datasetSpec.setPseudo()
558
+ datasetSpec.vo = self.taskSpec.vo
559
+ datasetSpec.nFiles = 0
560
+ datasetSpec.nFilesUsed = 0
561
+ datasetSpec.nFilesFinished = 0
562
+ datasetSpec.nFilesFailed = 0
563
+ datasetSpec.nFilesOnHold = 0
564
+ datasetSpec.nFilesWaiting = 0
565
+ datasetSpec.nFilesMissing = 0
566
+ datasetSpec.nEvents = 0
567
+ datasetSpec.nEventsUsed = 0
568
+ datasetSpec.nEventsToBeUsed = 0
569
+ datasetSpec.status = "defined"
570
+ if datasetSpec.type in JediDatasetSpec.getInputTypes() + ["random_seed"]:
571
+ datasetSpec.streamName = RefinerUtils.extractStreamName(tmpItem["value"])
572
+ if "expandedList" not in tmpItem:
573
+ tmpItem["expandedList"] = []
574
+ # dataset names could be comma-concatenated
575
+ datasetNameList = datasetSpec.datasetName.split(",")
576
+ # datasets could be added by incexec
577
+ incexecDS = f"dsFor{datasetSpec.streamName}"
578
+ # remove /XYZ
579
+ incexecDS = incexecDS.split("/")[0]
580
+ if incexecDS in taskParamMap:
581
+ for tmpDatasetName in taskParamMap[incexecDS].split(","):
582
+ if tmpDatasetName not in datasetNameList:
583
+ datasetNameList.append(tmpDatasetName)
584
+ # consolidation
585
+ if len(datasetNameList) > 1 and "consolidate" in tmpItem:
586
+ tmpIF = self.ddmIF.getInterface(self.taskSpec.vo, self.taskSpec.cloud)
587
+ if tmpIF:
588
+ containerName = tmpItem["consolidate"]
589
+ tmpStat = tmpIF.registerNewDataset(containerName)
590
+ if not tmpStat:
591
+ errStr = f"failed to register {containerName}"
592
+ raise JediException.ExternalTempError(errStr)
593
+ tmpDsListInCont = tmpIF.listDatasetsInContainer(containerName)
594
+ for tmpContName in datasetNameList:
595
+ tmpDsNameList = tmpIF.expandContainer(tmpContName)
596
+ for tmpDsName in tmpDsNameList:
597
+ if tmpDsName not in tmpDsListInCont:
598
+ tmpStat = tmpIF.addDatasetsToContainer(containerName, [tmpDsName])
599
+ if not tmpStat:
600
+ errStr = f"failed to add {tmpDsName} to {containerName}"
601
+ raise JediException.ExternalTempError(errStr)
602
+ datasetNameList = [containerName]
603
+ # loop over all dataset names
604
+ inDatasetSpecList = []
605
+ for datasetName in datasetNameList:
606
+ # skip empty
607
+ if datasetName == "":
608
+ continue
609
+ # expand
610
+ if datasetSpec.isPseudo() or datasetSpec.type in ["random_seed"] or datasetName == "DBR_LATEST":
611
+ # pseudo input
612
+ tmpDatasetNameList = [datasetName]
613
+ if self.taskSpec.is_work_segmented():
614
+ tmpDatasetNameList *= len(taskParamMap["segmentSpecs"])
615
+ else:
616
+ tmpIF = self.ddmIF.getInterface(self.taskSpec.vo, self.taskSpec.cloud)
617
+ if not tmpIF:
618
+ tmpDatasetNameList = []
619
+ else:
620
+ if "expand" in tmpItem and tmpItem["expand"] is True:
621
+ # expand dataset container
622
+ tmpDatasetNameList = tmpIF.expandContainer(datasetName)
623
+ # sort datasets to process online complete replicas first
624
+ tmp_ok_list = []
625
+ tmp_ng_list = []
626
+ for tmp_dataset_name in tmpDatasetNameList:
627
+ # skip the check if enough datasets are OK
628
+ if len(tmp_ok_list) > 10:
629
+ is_ok = True
630
+ else:
631
+ # check if complete replica is available at online endpoint
632
+ is_ok = False
633
+ tmp_dict = tmpIF.listDatasetReplicas(tmp_dataset_name)
634
+ for tmp_endpoint, tmp_data_list in tmp_dict.items():
635
+ tmp_data = tmp_data_list[0]
636
+ if (
637
+ tmp_data["total"]
638
+ and tmp_data["total"] == tmp_data["found"]
639
+ and self.siteMapper.is_readable_remotely(tmp_endpoint)
640
+ ):
641
+ is_ok = True
642
+ break
643
+ if is_ok:
644
+ tmp_ok_list.append(tmp_dataset_name)
645
+ else:
646
+ tmp_ng_list.append(tmp_dataset_name)
647
+ tmpDatasetNameList = tmp_ok_list + tmp_ng_list
648
+ else:
649
+ # normal dataset name
650
+ tmpDatasetNameList = tmpIF.listDatasets(datasetName)
651
+ i_element = 0
652
+ for elementDatasetName in tmpDatasetNameList:
653
+ if "expandedList" in tmpItem:
654
+ if elementDatasetName not in tmpItem["expandedList"]:
655
+ tmpItem["expandedList"].append(elementDatasetName)
656
+ inDatasetSpec = copy.copy(datasetSpec)
657
+ inDatasetSpec.datasetName = elementDatasetName
658
+ if nIn > 0 or not self.taskSpec.is_hpo_workflow():
659
+ inDatasetSpec.containerName = datasetName
660
+ else:
661
+ if self.taskSpec.is_work_segmented():
662
+ inDatasetSpec.containerName = "{}/{}".format(
663
+ taskParamMap["segmentSpecs"][i_element]["name"], taskParamMap["segmentSpecs"][i_element]["id"]
664
+ )
665
+ else:
666
+ inDatasetSpec.containerName = "None/None"
667
+ inDatasetSpecList.append(inDatasetSpec)
668
+ i_element += 1
669
+ # empty input
670
+ if inDatasetSpecList == [] and self.oldTaskStatus != "rerefine":
671
+ errStr = f'doBasicRefine : unknown input dataset "{datasetSpec.datasetName}"'
672
+ self.taskSpec.setErrDiag(errStr)
673
+ if datasetSpec.datasetName not in self.unknownDatasetList:
674
+ self.unknownDatasetList.append(datasetSpec.datasetName)
675
+ raise JediException.UnknownDatasetError(errStr)
676
+ # set master flag
677
+ for inDatasetSpec in inDatasetSpecList:
678
+ if nIn == 0:
679
+ # master
680
+ self.inMasterDatasetSpec.append(inDatasetSpec)
681
+ else:
682
+ # secondary
683
+ self.inSecDatasetSpecList.append(inDatasetSpec)
684
+ nIn += 1
685
+ continue
686
+ if datasetSpec.type in ["output", "log"]:
687
+ # check endpoint
688
+ if (
689
+ datasetSpec.destination is not None
690
+ and re.search("^[a-zA-Z0-9_-]+$", datasetSpec.destination)
691
+ and datasetSpec.destination not in checked_endpoints
692
+ ):
693
+ checked_endpoints.add(datasetSpec.destination)
694
+ tmp_if = self.ddmIF.getInterface(self.taskSpec.vo, self.taskSpec.cloud)
695
+ if tmp_if:
696
+ tmp_status, tmp_output = tmp_if.check_endpoint(datasetSpec.destination)
697
+ if tmp_status is None:
698
+ # unknown error
699
+ raise JediException.ExternalTempError(tmp_output)
700
+ elif tmp_status is False:
701
+ # bad endpoint
702
+ raise JediException.TempBadStorageError(tmp_output)
703
+ # collect output types
704
+ if datasetSpec.type not in nOutMap:
705
+ nOutMap[datasetSpec.type] = 0
706
+ # make stream name
707
+ if not datasetSpec.is_merge_only():
708
+ datasetSpec.streamName = f"{datasetSpec.type.upper()}{nOutMap[datasetSpec.type]}"
709
+ else:
710
+ datasetSpec.streamName = "LOG_MERGE"
711
+ nOutMap[datasetSpec.type] += 1
712
+ # set attribute for event service
713
+ if self.taskSpec.useEventService() and "objectStore" in taskParamMap and datasetSpec.type in ["output"]:
714
+ datasetSpec.setObjectStore(taskParamMap["objectStore"])
715
+ # extract output filename template and change the value field
716
+ outFileTemplate, tmpItem["value"] = RefinerUtils.extractReplaceOutFileTemplate(tmpItem["value"], datasetSpec.streamName)
717
+ # make output template
718
+ if outFileTemplate is not None:
719
+ if "offset" in tmpItem:
720
+ offsetVal = 1 + tmpItem["offset"]
721
+ else:
722
+ offsetVal = 1
723
+ outTemplateMap = {
724
+ "jediTaskID": self.taskSpec.jediTaskID,
725
+ "serialNr": offsetVal,
726
+ "streamName": datasetSpec.streamName,
727
+ "filenameTemplate": outFileTemplate,
728
+ "outtype": datasetSpec.type,
729
+ }
730
+ if datasetSpec.outputMapKey() in self.outputTemplateMap:
731
+ # multiple files are associated to the same output datasets
732
+ self.outputTemplateMap[datasetSpec.outputMapKey()].append(outTemplateMap)
733
+ # don't insert the same output dataset
734
+ continue
735
+ self.outputTemplateMap[datasetSpec.outputMapKey()] = [outTemplateMap]
736
+ # append
737
+ self.outDatasetSpecList.append(datasetSpec)
738
+ # used only in merge
739
+ if datasetSpec.is_merge_only():
740
+ continue
741
+ # make unmerged dataset
742
+ if "mergeOutput" in taskParamMap and taskParamMap["mergeOutput"] is True:
743
+ umDatasetSpec = JediDatasetSpec()
744
+ umDatasetSpec.datasetName = "panda.um." + datasetSpec.datasetName
745
+ umDatasetSpec.jediTaskID = self.taskSpec.jediTaskID
746
+ umDatasetSpec.storageToken = "TOMERGE"
747
+ umDatasetSpec.vo = datasetSpec.vo
748
+ umDatasetSpec.type = "tmpl_trn_" + datasetSpec.type
749
+ umDatasetSpec.nFiles = 0
750
+ umDatasetSpec.nFilesUsed = 0
751
+ umDatasetSpec.nFilesToBeUsed = 0
752
+ umDatasetSpec.nFilesFinished = 0
753
+ umDatasetSpec.nFilesFailed = 0
754
+ umDatasetSpec.nFilesOnHold = 0
755
+ umDatasetSpec.status = "defined"
756
+ umDatasetSpec.streamName = datasetSpec.streamName
757
+ if datasetSpec.isAllowedNoOutput():
758
+ umDatasetSpec.allowNoOutput()
759
+ # ratio
760
+ if datasetSpec.getRatioToMaster() > 1:
761
+ umDatasetSpec.setDatasetAttribute(f"ratio={datasetSpec.getRatioToMaster()}")
762
+ # make unmerged output template
763
+ if outFileTemplate is not None:
764
+ umOutTemplateMap = {
765
+ "jediTaskID": self.taskSpec.jediTaskID,
766
+ "serialNr": 1,
767
+ "streamName": umDatasetSpec.streamName,
768
+ "outtype": datasetSpec.type,
769
+ }
770
+ # append temporary name
771
+ if "umNameAtEnd" in taskParamMap and taskParamMap["umNameAtEnd"] is True:
772
+ # append temporary name at the end
773
+ umOutTemplateMap["filenameTemplate"] = outFileTemplate + ".panda.um"
774
+ else:
775
+ umOutTemplateMap["filenameTemplate"] = "panda.um." + outFileTemplate
776
+ if umDatasetSpec.outputMapKey() in self.outputTemplateMap:
777
+ # multiple files are associated to the same output datasets
778
+ self.outputTemplateMap[umDatasetSpec.outputMapKey()].append(umOutTemplateMap)
779
+ # don't insert the same output dataset
780
+ continue
781
+ self.outputTemplateMap[umDatasetSpec.outputMapKey()] = [umOutTemplateMap]
782
+ # use log as master for merging
783
+ if datasetSpec.type == "log":
784
+ self.unmergeMasterDatasetSpec[datasetSpec.outputMapKey()] = umDatasetSpec
785
+ else:
786
+ # append
787
+ self.unmergeDatasetSpecMap[datasetSpec.outputMapKey()] = umDatasetSpec
788
+ # set attributes for merging
789
+ if "mergeOutput" in taskParamMap and taskParamMap["mergeOutput"] is True:
790
+ self.setSplitRule(None, 1, JediTaskSpec.splitRuleToken["mergeOutput"])
791
+ # make job parameters
792
+ rndmSeedOffset = None
793
+ firstEventOffset = None
794
+ jobParameters = ""
795
+ for tmpItem in taskParamMap["jobParameters"]:
796
+ if "value" in tmpItem:
797
+ # hidden parameter
798
+ if "hidden" in tmpItem and tmpItem["hidden"] is True:
799
+ continue
800
+ # add tags for ES-only parameters
801
+ esOnly = False
802
+ if "es_only" in tmpItem and tmpItem["es_only"] is True:
803
+ esOnly = True
804
+ if esOnly:
805
+ jobParameters += "<PANDA_ES_ONLY>"
806
+ jobParameters += f"{tmpItem['value']}"
807
+ if esOnly:
808
+ jobParameters += "</PANDA_ES_ONLY>"
809
+ # padding
810
+ if "padding" in tmpItem and tmpItem["padding"] is False:
811
+ pass
812
+ else:
813
+ jobParameters += " "
814
+ # get offset for random seed and first event
815
+ if tmpItem["type"] == "template" and tmpItem["param_type"] == "number":
816
+ if "${RNDMSEED}" in tmpItem["value"]:
817
+ if "offset" in tmpItem:
818
+ rndmSeedOffset = tmpItem["offset"]
819
+ else:
820
+ rndmSeedOffset = 0
821
+ elif "${FIRSTEVENT}" in tmpItem["value"]:
822
+ if "offset" in tmpItem:
823
+ firstEventOffset = tmpItem["offset"]
824
+ jobParameters = jobParameters[:-1]
825
+ # append parameters for event service merging if necessary
826
+ esmergeParams = self.getParamsForEventServiceMerging(taskParamMap)
827
+ if esmergeParams is not None:
828
+ jobParameters += esmergeParams
829
+ self.setJobParamsTemplate(jobParameters)
830
+ # set payload identifier
831
+ self.taskSpec.requestType = self.create_payload_identifier(taskParamMap)
832
+ # set random seed offset
833
+ if rndmSeedOffset is not None:
834
+ self.setSplitRule(None, rndmSeedOffset, JediTaskSpec.splitRuleToken["randomSeed"])
835
+ if firstEventOffset is not None:
836
+ self.setSplitRule(None, firstEventOffset, JediTaskSpec.splitRuleToken["firstEvent"])
837
+ # send HPO request
838
+ if self.taskSpec.is_hpo_workflow():
839
+ try:
840
+ data = copy.copy(taskParamMap["hpoRequestData"])
841
+ data["workload_id"] = self.taskSpec.jediTaskID
842
+ data["is_pseudo_input"] = True
843
+ req = {
844
+ "requester": "panda",
845
+ "request_type": idds.common.constants.RequestType.HyperParameterOpt,
846
+ "transform_tag": idds.common.constants.RequestType.HyperParameterOpt.value,
847
+ "status": idds.common.constants.RequestStatus.New,
848
+ "priority": 0,
849
+ "lifetime": 30,
850
+ "request_metadata": data,
851
+ }
852
+ c = iDDS_Client(idds.common.utils.get_rest_host())
853
+ self.tmpLog.debug(f"req {str(req)}")
854
+ ret = c.add_request(**req)
855
+ self.tmpLog.debug(f"got requestID={str(ret)}")
856
+ except Exception as e:
857
+ errStr = f"iDDS failed with {str(e)}"
858
+ raise JediException.ExternalTempError(errStr)
859
+
860
+ return
861
+
862
+ # replace placeholder with dict provided by prepro job
863
+ def replacePlaceHolders(self, paramItem, placeHolderName, newValue):
864
+ if isinstance(paramItem, dict):
865
+ # loop over all dict params
866
+ for tmpParName, tmpParVal in paramItem.items():
867
+ if tmpParVal == placeHolderName:
868
+ # replace placeholder
869
+ paramItem[tmpParName] = newValue
870
+ elif isinstance(tmpParVal, dict) or isinstance(tmpParVal, list):
871
+ # recursive execution
872
+ self.replacePlaceHolders(tmpParVal, placeHolderName, newValue)
873
+ elif isinstance(paramItem, list):
874
+ # loop over all list items
875
+ for tmpItem in paramItem:
876
+ self.replacePlaceHolders(tmpItem, placeHolderName, newValue)
877
+
878
+ # refinement procedure for preprocessing
879
+ def doPreProRefine(self, taskParamMap):
880
+ # no preprocessing
881
+ if "preproSpec" not in taskParamMap:
882
+ return None, taskParamMap
883
+ # already preprocessed
884
+ if self.taskSpec.checkPreProcessed():
885
+ # get replaced task params
886
+ tmpStat, tmpJsonStr = self.taskBufferIF.getPreprocessMetadata_JEDI(self.taskSpec.jediTaskID)
887
+ try:
888
+ # replace placeholders
889
+ replaceParams = RefinerUtils.decodeJSON(tmpJsonStr)
890
+ self.tmpLog.debug("replace placeholders with " + str(replaceParams))
891
+ for tmpKey, tmpVal in replaceParams.items():
892
+ self.replacePlaceHolders(taskParamMap, tmpKey, tmpVal)
893
+ except Exception:
894
+ errtype, errvalue = sys.exc_info()[:2]
895
+ self.tmpLog.error(f"{self.__class__.__name__} failed to get additional task params with {errtype}:{errvalue}")
896
+ return False, taskParamMap
897
+ # succeeded
898
+ self.updatedTaskParams = taskParamMap
899
+ return None, taskParamMap
900
+ # make dummy dataset to keep track of preprocessing
901
+ datasetSpec = JediDatasetSpec()
902
+ datasetSpec.datasetName = f"panda.pp.in.{uuid.uuid4()}.{self.taskSpec.jediTaskID}"
903
+ datasetSpec.jediTaskID = self.taskSpec.jediTaskID
904
+ datasetSpec.type = "pp_input"
905
+ datasetSpec.vo = self.taskSpec.vo
906
+ datasetSpec.nFiles = 1
907
+ datasetSpec.nFilesUsed = 0
908
+ datasetSpec.nFilesToBeUsed = 1
909
+ datasetSpec.nFilesFinished = 0
910
+ datasetSpec.nFilesFailed = 0
911
+ datasetSpec.nFilesOnHold = 0
912
+ datasetSpec.status = "ready"
913
+ self.inMasterDatasetSpec.append(datasetSpec)
914
+ # make file
915
+ fileSpec = JediFileSpec()
916
+ fileSpec.jediTaskID = datasetSpec.jediTaskID
917
+ fileSpec.type = datasetSpec.type
918
+ fileSpec.status = "ready"
919
+ fileSpec.lfn = "pseudo_lfn"
920
+ fileSpec.attemptNr = 0
921
+ fileSpec.maxAttempt = 3
922
+ fileSpec.keepTrack = 1
923
+ datasetSpec.addFile(fileSpec)
924
+ # make log dataset
925
+ logDatasetSpec = JediDatasetSpec()
926
+ logDatasetSpec.datasetName = f"panda.pp.log.{uuid.uuid4()}.{self.taskSpec.jediTaskID}"
927
+ logDatasetSpec.jediTaskID = self.taskSpec.jediTaskID
928
+ logDatasetSpec.type = "tmpl_pp_log"
929
+ logDatasetSpec.streamName = "PP_LOG"
930
+ logDatasetSpec.vo = self.taskSpec.vo
931
+ logDatasetSpec.nFiles = 0
932
+ logDatasetSpec.nFilesUsed = 0
933
+ logDatasetSpec.nFilesToBeUsed = 0
934
+ logDatasetSpec.nFilesFinished = 0
935
+ logDatasetSpec.nFilesFailed = 0
936
+ logDatasetSpec.nFilesOnHold = 0
937
+ logDatasetSpec.status = "defined"
938
+ self.outDatasetSpecList.append(logDatasetSpec)
939
+ # make output template for log
940
+ outTemplateMap = {
941
+ "jediTaskID": self.taskSpec.jediTaskID,
942
+ "serialNr": 1,
943
+ "streamName": logDatasetSpec.streamName,
944
+ "filenameTemplate": f"{logDatasetSpec.datasetName}._${{SN}}.log.tgz",
945
+ "outtype": re.sub("^tmpl_", "", logDatasetSpec.type),
946
+ }
947
+ self.outputTemplateMap[logDatasetSpec.outputMapKey()] = [outTemplateMap]
948
+ # set split rule to use preprocessing
949
+ self.taskSpec.setPrePro()
950
+ # set task status
951
+ self.taskSpec.status = "topreprocess"
952
+ # return
953
+ return True, taskParamMap
954
+
955
+ # set split rule
956
+ def setSplitRule(self, taskParamMap, key_or_value, rule_token):
957
+ if taskParamMap is not None:
958
+ if key_or_value not in taskParamMap:
959
+ self.taskSpec.splitRule = task_split_rules.remove_rule(self.taskSpec.splitRule, rule_token)
960
+ return
961
+ tmpStr = f"{rule_token}={taskParamMap[key_or_value]}"
962
+ else:
963
+ if key_or_value is None:
964
+ self.taskSpec.splitRule = task_split_rules.remove_rule(self.taskSpec.splitRule, rule_token)
965
+ return
966
+ tmpStr = f"{rule_token}={key_or_value}"
967
+ if self.taskSpec.splitRule in [None, ""]:
968
+ self.taskSpec.splitRule = tmpStr
969
+ else:
970
+ tmpMatch = re.search(rule_token + "=(-*\d+)(,-*\d+)*", self.taskSpec.splitRule)
971
+ if tmpMatch is None:
972
+ # append
973
+ self.taskSpec.splitRule += f",{tmpStr}"
974
+ else:
975
+ # replace
976
+ self.taskSpec.splitRule = self.taskSpec.splitRule.replace(tmpMatch.group(0), tmpStr)
977
+ return
978
+
979
+ # get parameters for event service merging
980
+ def getParamsForEventServiceMerging(self, taskParamMap):
981
+ # no event service
982
+ if not self.taskSpec.useEventService() or self.taskSpec.on_site_merging():
983
+ return None
984
+ # extract parameters
985
+ transPath = "UnDefined"
986
+ jobParameters = "UnDefined"
987
+ if "esmergeSpec" in taskParamMap:
988
+ if "transPath" in taskParamMap["esmergeSpec"]:
989
+ transPath = taskParamMap["esmergeSpec"]["transPath"]
990
+ if "jobParameters" in taskParamMap["esmergeSpec"]:
991
+ jobParameters = jobParameters["esmergeSpec"]["jobParameters"]
992
+ # return
993
+ return "<PANDA_ESMERGE_TRF>" + transPath + "</PANDA_ESMERGE_TRF>" + "<PANDA_ESMERGE_JOBP>" + jobParameters + "</PANDA_ESMERGE_JOBP>"
994
+
995
+
996
+ Interaction.installSC(TaskRefinerBase)