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,611 @@
1
+ import datetime
2
+ import itertools
3
+ import sys
4
+ import time
5
+ import traceback
6
+
7
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
8
+ from pandacommon.pandautils.PandaUtils import naive_utcnow
9
+
10
+ from pandajedi.jediconfig import jedi_config
11
+ from pandajedi.jedicore import Interaction, JediException
12
+ from pandajedi.jedicore.FactoryBase import FactoryBase
13
+ from pandajedi.jedicore.MsgWrapper import MsgWrapper
14
+ from pandajedi.jedicore.ThreadUtils import ListWithLock, ThreadPool, WorkerThread
15
+ from pandajedi.jedirefine import RefinerUtils
16
+ from pandaserver.dataservice.ddm import rucioAPI
17
+ from pandaserver.taskbuffer.DataCarousel import DataCarouselInterface
18
+ from pandaserver.taskbuffer.JediTaskSpec import JediTaskSpec
19
+
20
+ from .JediKnight import JediKnight
21
+
22
+ logger = PandaLogger().getLogger(__name__.split(".")[-1])
23
+
24
+
25
+ # worker class to refine TASK_PARAM to fill JEDI tables
26
+ class TaskRefiner(JediKnight, FactoryBase):
27
+ # constructor
28
+ def __init__(self, commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels):
29
+ self.vos = self.parseInit(vos)
30
+ self.prodSourceLabels = self.parseInit(prodSourceLabels)
31
+ JediKnight.__init__(self, commuChannel, taskBufferIF, ddmIF, logger)
32
+ FactoryBase.__init__(self, self.vos, self.prodSourceLabels, logger, jedi_config.taskrefine.modConfig)
33
+
34
+ # main
35
+ def start(self):
36
+ # start base classes
37
+ JediKnight.start(self)
38
+ FactoryBase.initializeMods(self, self.taskBufferIF, self.ddmIF)
39
+ # get data carousel interface
40
+ data_carousel_interface = DataCarouselInterface(self.taskBufferIF)
41
+ if data_carousel_interface is None:
42
+ # data carousel interface is undefined
43
+ logger.error(f"data carousel interface is undefined; skipped")
44
+ return
45
+ # go into main loop
46
+ while True:
47
+ startTime = naive_utcnow()
48
+ try:
49
+ # get logger
50
+ tmpLog = MsgWrapper(logger)
51
+ tmpLog.debug("start")
52
+ # loop over all vos
53
+ for vo in self.vos:
54
+ # loop over all sourceLabels
55
+ for prodSourceLabel in self.prodSourceLabels:
56
+ # get the list of tasks to refine
57
+ tmpList = self.taskBufferIF.getTasksToRefine_JEDI(vo, prodSourceLabel)
58
+ if tmpList is None:
59
+ # failed
60
+ tmpLog.error("failed to get the list of tasks to refine")
61
+ else:
62
+ tmpLog.debug(f"got {len(tmpList)} tasks")
63
+ # put to a locked list
64
+ taskList = ListWithLock(tmpList)
65
+ # make thread pool
66
+ threadPool = ThreadPool()
67
+ # get work queue mapper
68
+ workQueueMapper = self.taskBufferIF.getWorkQueueMap()
69
+ # make workers
70
+ nWorker = jedi_config.taskrefine.nWorkers
71
+ for _ in range(nWorker):
72
+ thr = TaskRefinerThread(taskList, threadPool, self.taskBufferIF, self.ddmIF, self, workQueueMapper, data_carousel_interface)
73
+ thr.start()
74
+ # join
75
+ threadPool.join()
76
+ except Exception:
77
+ errtype, errvalue = sys.exc_info()[:2]
78
+ tmpLog.error(f"failed in {self.__class__.__name__}.start() with {errtype.__name__} {errvalue}")
79
+ tmpLog.error(f"Traceback: {traceback.format_exc()}")
80
+ # sleep if needed
81
+ loopCycle = jedi_config.taskrefine.loopCycle
82
+ timeDelta = naive_utcnow() - startTime
83
+ sleepPeriod = loopCycle - timeDelta.seconds
84
+ if sleepPeriod > 0:
85
+ time.sleep(sleepPeriod)
86
+ # randomize cycle
87
+ self.randomSleep(max_val=loopCycle)
88
+
89
+
90
+ # thread for real worker
91
+ class TaskRefinerThread(WorkerThread):
92
+ # constructor
93
+ def __init__(self, taskList, threadPool, taskbufferIF, ddmIF, implFactory, workQueueMapper, data_carousel_interface=None):
94
+ # initialize worker with no semaphore
95
+ WorkerThread.__init__(self, None, threadPool, logger)
96
+ # attributes
97
+ self.taskList = taskList
98
+ self.taskBufferIF = taskbufferIF
99
+ self.ddmIF = ddmIF
100
+ self.implFactory = implFactory
101
+ self.workQueueMapper = workQueueMapper
102
+ self.data_carousel_interface = data_carousel_interface
103
+ self.msgType = "taskrefiner"
104
+
105
+ # main
106
+ def runImpl(self):
107
+ while True:
108
+ try:
109
+ # get a part of list
110
+ nTasks = 10
111
+ taskList = self.taskList.get(nTasks)
112
+ # no more datasets
113
+ if len(taskList) == 0:
114
+ self.logger.info(f"{self.__class__.__name__} terminating since no more items")
115
+ return
116
+ # loop over all tasks
117
+ for jediTaskID, splitRule, taskStatus, parent_tid in taskList:
118
+ # make logger
119
+ tmpLog = MsgWrapper(self.logger, f"< jediTaskID={jediTaskID} >", monToken=f"<jediTaskID={jediTaskID}>")
120
+ tmpLog.debug("start")
121
+ tmpStat = Interaction.SC_SUCCEEDED
122
+ errStr = ""
123
+ prodSourceLabel = None
124
+ # read task parameters
125
+ try:
126
+ taskParam = None
127
+ taskParam = self.taskBufferIF.getTaskParamsWithID_JEDI(jediTaskID)
128
+ taskParamMap = RefinerUtils.decodeJSON(taskParam)
129
+ except Exception:
130
+ errtype, errvalue = sys.exc_info()[:2]
131
+ errStr = f"conversion to map from json failed with {errtype.__name__}:{errvalue}"
132
+ tmpLog.debug(taskParam)
133
+ tmpLog.error(errStr)
134
+ continue
135
+ tmpStat = Interaction.SC_FAILED
136
+ # get impl
137
+ if tmpStat == Interaction.SC_SUCCEEDED:
138
+ tmpLog.info("getting Impl")
139
+ try:
140
+ # get VO and sourceLabel
141
+ vo = taskParamMap["vo"]
142
+ prodSourceLabel = taskParamMap["prodSourceLabel"]
143
+ taskType = taskParamMap["taskType"]
144
+ tmpLog.info(f"vo={vo} sourceLabel={prodSourceLabel} taskType={taskType}")
145
+ # get impl
146
+ impl = self.implFactory.instantiateImpl(vo, prodSourceLabel, taskType, self.taskBufferIF, self.ddmIF)
147
+ if impl is None:
148
+ # task refiner is undefined
149
+ errStr = f"task refiner is undefined for vo={vo} sourceLabel={prodSourceLabel}"
150
+ tmpLog.error(errStr)
151
+ tmpStat = Interaction.SC_FAILED
152
+ # get data carousel config map
153
+ dc_config_map = self.data_carousel_interface.dc_config_map
154
+ except Exception:
155
+ errtype, errvalue = sys.exc_info()[:2]
156
+ errStr = f"failed to get task refiner with {errtype.__name__}:{errvalue}"
157
+ tmpLog.error(errStr)
158
+ tmpStat = Interaction.SC_FAILED
159
+ # adjust task parameters
160
+ if tmpStat == Interaction.SC_SUCCEEDED:
161
+ tmpLog.info("adjusting task parameters")
162
+ try:
163
+ # Data Carousel; for all analysis tasks, and production tasks with "panda_data_carousel"
164
+ if dc_config_map and ((taskType == "anal" and prodSourceLabel == "user") or taskParamMap.get("panda_data_carousel")):
165
+ if taskParamMap.get("noInput"):
166
+ # noInput task, skipped
167
+ pass
168
+ elif taskType == "anal" and (taskParamMap.get("nFiles") or taskParamMap.get("nEvents") or taskParamMap.get("skipFilesUsedBy")):
169
+ # for analysis tasks with nFiles or nEvents or skipFilesUsedBy, task does not need all files from inputs, not to stage, skipped
170
+ pass
171
+ elif "inputPreStaging" not in taskParamMap:
172
+ if dc_config_map.early_access_users and dc_config_map.early_access_users[0] == "ALL":
173
+ # enable input pre-staging for all users
174
+ taskParamMap["inputPreStaging"] = True
175
+ tmpLog.info(f"set inputPreStaging for data carousel ALL users")
176
+ elif (user_name := taskParamMap.get("userName")) in dc_config_map.early_access_users:
177
+ # enable input pre-staging for early access user
178
+ taskParamMap["inputPreStaging"] = True
179
+ tmpLog.info(f"set inputPreStaging for data carousel early access user {user_name}")
180
+ except Exception:
181
+ errtype, errvalue = sys.exc_info()[:2]
182
+ errStr = f"failed to adjust task parameters with {errtype.__name__}:{errvalue}"
183
+ tmpLog.error(errStr)
184
+ tmpStat = Interaction.SC_FAILED
185
+ # extract common parameters
186
+ if tmpStat == Interaction.SC_SUCCEEDED:
187
+ tmpLog.info("extracting common")
188
+ try:
189
+ # initialize impl
190
+ impl.initializeRefiner(tmpLog)
191
+ impl.oldTaskStatus = taskStatus
192
+ # extract common parameters
193
+ impl.extractCommon(jediTaskID, taskParamMap, self.workQueueMapper, splitRule)
194
+ # set parent tid
195
+ if parent_tid not in [None, jediTaskID]:
196
+ impl.taskSpec.parent_tid = parent_tid
197
+ except Exception:
198
+ errtype, errvalue = sys.exc_info()[:2]
199
+ # on hold in case of external error
200
+ if errtype == JediException.ExternalTempError:
201
+ tmpErrStr = f"pending due to external problem. {errvalue}"
202
+ setFrozenTime = True
203
+ impl.taskSpec.status = taskStatus
204
+ impl.taskSpec.setOnHold()
205
+ impl.taskSpec.setErrDiag(tmpErrStr)
206
+ # not to update some task attributes
207
+ impl.taskSpec.resetRefinedAttrs()
208
+ tmpLog.info(tmpErrStr)
209
+ self.taskBufferIF.updateTask_JEDI(
210
+ impl.taskSpec,
211
+ {"jediTaskID": impl.taskSpec.jediTaskID},
212
+ oldStatus=[taskStatus],
213
+ insertUnknown=impl.unknownDatasetList,
214
+ setFrozenTime=setFrozenTime,
215
+ )
216
+ continue
217
+ errStr = f"failed to extract common parameters with {errtype.__name__}:{errvalue} {traceback.format_exc()}"
218
+ tmpLog.error(errStr)
219
+ tmpStat = Interaction.SC_FAILED
220
+ # check attribute length
221
+ if tmpStat == Interaction.SC_SUCCEEDED:
222
+ tmpLog.info("checking attribute length")
223
+ if not impl.taskSpec.checkAttrLength():
224
+ tmpLog.error(impl.taskSpec.errorDialog)
225
+ tmpStat = Interaction.SC_FAILED
226
+ # check parent
227
+ noWaitParent = False
228
+ parentState = None
229
+ if tmpStat == Interaction.SC_SUCCEEDED and parent_tid not in [None, jediTaskID]:
230
+ tmpLog.info("check parent task")
231
+ try:
232
+ tmpStat = self.taskBufferIF.checkParentTask_JEDI(parent_tid, jediTaskID)
233
+ parentState = tmpStat
234
+ if tmpStat == "completed":
235
+ # parent is done
236
+ tmpStat = Interaction.SC_SUCCEEDED
237
+ elif tmpStat is None or tmpStat == "running":
238
+ if not impl.taskSpec.noWaitParent():
239
+ # parent is running
240
+ errStr = f"pending until parent task {parent_tid} is done"
241
+ impl.taskSpec.status = taskStatus
242
+ impl.taskSpec.setOnHold()
243
+ impl.taskSpec.setErrDiag(errStr)
244
+ # not to update some task attributes
245
+ impl.taskSpec.resetRefinedAttrs()
246
+ tmpLog.info(errStr)
247
+ self.taskBufferIF.updateTask_JEDI(
248
+ impl.taskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus], setFrozenTime=False
249
+ )
250
+ continue
251
+ else:
252
+ # not wait for parent
253
+ tmpStat = Interaction.SC_SUCCEEDED
254
+ noWaitParent = True
255
+ else:
256
+ # parent is corrupted
257
+ tmpStat = Interaction.SC_FAILED
258
+ tmpErrStr = f"parent task {parent_tid} failed to complete"
259
+ impl.taskSpec.setErrDiag(tmpErrStr)
260
+ except Exception:
261
+ errtype, errvalue = sys.exc_info()[:2]
262
+ errStr = f"failed to check parent task with {errtype.__name__}:{errvalue}"
263
+ tmpLog.error(errStr)
264
+ tmpStat = Interaction.SC_FAILED
265
+
266
+ # refine
267
+ if tmpStat == Interaction.SC_SUCCEEDED:
268
+ tmpLog.info(f"refining with {impl.__class__.__name__}")
269
+ try:
270
+ tmpStat = impl.doRefine(jediTaskID, taskParamMap)
271
+ except Exception:
272
+ errtype, errvalue = sys.exc_info()[:2]
273
+ # wait unknown input if noWaitParent or waitInput
274
+ toFinish = False
275
+ if (
276
+ ((impl.taskSpec.noWaitParent() or impl.taskSpec.waitInput()) and errtype == JediException.UnknownDatasetError)
277
+ or parentState == "running"
278
+ or errtype in [Interaction.JEDITemporaryError, JediException.ExternalTempError, JediException.TempBadStorageError]
279
+ ):
280
+ if impl.taskSpec.noWaitParent() and errtype == JediException.UnknownDatasetError and parentState != "running":
281
+ if impl.taskSpec.allowEmptyInput():
282
+ tmpErrStr = f"finishing due to missing input while parent is {parentState}"
283
+ toFinish = True
284
+ setFrozenTime = False
285
+ else:
286
+ tmpErrStr = f"pending due to missing input while parent is {parentState}"
287
+ setFrozenTime = True
288
+ elif impl.taskSpec.noWaitParent() or parentState == "running":
289
+ tmpErrStr = f"pending until parent produces input. parent is {parentState}"
290
+ setFrozenTime = False
291
+ elif errtype == Interaction.JEDITemporaryError or errtype == JediException.ExternalTempError:
292
+ tmpErrStr = f"pending due to external temporary problem. {errvalue}"
293
+ setFrozenTime = True
294
+ elif errtype == JediException.TempBadStorageError:
295
+ tmpErrStr = f"pending due to temporary storage issue. {errvalue}"
296
+ setFrozenTime = True
297
+ else:
298
+ tmpErrStr = "pending until input is staged"
299
+ setFrozenTime = True
300
+ if toFinish:
301
+ impl.taskSpec.status = "finishing"
302
+ else:
303
+ impl.taskSpec.status = taskStatus
304
+ impl.taskSpec.setOnHold()
305
+ impl.taskSpec.setErrDiag(tmpErrStr)
306
+ # not to update some task attributes
307
+ impl.taskSpec.resetRefinedAttrs()
308
+ tmpLog.info(tmpErrStr)
309
+ self.taskBufferIF.updateTask_JEDI(
310
+ impl.taskSpec,
311
+ {"jediTaskID": impl.taskSpec.jediTaskID},
312
+ oldStatus=[taskStatus],
313
+ insertUnknown=impl.unknownDatasetList,
314
+ setFrozenTime=setFrozenTime,
315
+ )
316
+ continue
317
+ elif (
318
+ not (impl.taskSpec.noWaitParent() or impl.taskSpec.waitInput())
319
+ and errtype == JediException.UnknownDatasetError
320
+ and impl.taskSpec.allowEmptyInput()
321
+ ):
322
+ impl.taskSpec.status = "finishing"
323
+ tmpErrStr = f"finishing due to missing input after parent is {parentState}"
324
+ impl.taskSpec.setErrDiag(tmpErrStr)
325
+ # not to update some task attributes
326
+ impl.taskSpec.resetRefinedAttrs()
327
+ tmpLog.info(tmpErrStr)
328
+ self.taskBufferIF.updateTask_JEDI(
329
+ impl.taskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus], insertUnknown=impl.unknownDatasetList
330
+ )
331
+ continue
332
+ else:
333
+ errStr = f"failed to refine task with {errtype.__name__}:{errvalue}"
334
+ tmpLog.error(errStr)
335
+ tmpStat = Interaction.SC_FAILED
336
+ # data carousel (input pre-staging) ; currently for all analysis tasks, and production tasks with "panda_data_carousel"
337
+ if tmpStat == Interaction.SC_SUCCEEDED:
338
+ # set of datasets requiring and not requiring staging
339
+ to_staging_datasets = set()
340
+ no_staging_datasets = set()
341
+ disk_datasets = set()
342
+ # check datasets to pre-stage
343
+ if taskParamMap.get("inputPreStaging") and (
344
+ (taskParamMap.get("taskType") == "anal" and taskParamMap.get("prodSourceLabel") == "user")
345
+ or taskParamMap.get("panda_data_carousel")
346
+ ):
347
+ tmpLog.info("checking about data carousel")
348
+ try:
349
+ # get the list of dataset names (and DIDs) required to check; currently only master input datasets
350
+ dsname_list = []
351
+ for dataset_spec in impl.inMasterDatasetSpec:
352
+ dataset_name = dataset_spec.datasetName
353
+ dataset_did = None
354
+ try:
355
+ dataset_did = rucioAPI.get_did_str(dataset_name)
356
+ except Exception:
357
+ pass
358
+ dsname_list.append(dataset_name)
359
+ if dataset_did is not None:
360
+ dsname_list.append(dataset_did)
361
+ # check input datasets to prestage
362
+ try:
363
+ prestaging_list, ds_list_dict = self.data_carousel_interface.get_input_datasets_to_prestage(
364
+ jediTaskID, taskParamMap, dsname_list=dsname_list
365
+ )
366
+ except Exception as e:
367
+ # got error (e.g. due to DDM error); skip and retry in next cycle
368
+ tmpLog.error(f"failed to check input datasets to prestage ; got {e} ; skip and retry next time")
369
+ continue
370
+ # found no datasets only on tape to prestage
371
+ if pseudo_coll_list := ds_list_dict["pseudo_coll_list"]:
372
+ # update no_staging_datasets with pseudo inputs
373
+ tmpLog.debug(f"pseudo inputs: {pseudo_coll_list}")
374
+ no_staging_datasets.update(set(pseudo_coll_list))
375
+ if empty_coll_list := ds_list_dict["empty_coll_list"]:
376
+ # update no_staging_datasets with empty input collections
377
+ tmpLog.debug(f"empty input collections: {empty_coll_list}")
378
+ no_staging_datasets.update(set(empty_coll_list))
379
+ if unfound_coll_list := ds_list_dict["unfound_coll_list"]:
380
+ # some input collections unfound
381
+ if taskParamMap.get("waitInput"):
382
+ # task has waitInput; to be checked again by TaskRefiner later
383
+ tmpLog.debug(f"task has waitInput, waiting for input collections to be created: {unfound_coll_list}; skipped")
384
+ else:
385
+ # not to wait input; update no_staging_datasets with unfound input collections
386
+ tmpLog.debug(f"some input collections not found: {unfound_coll_list}")
387
+ no_staging_datasets.update(set(unfound_coll_list))
388
+ if no_tape_coll_did_list := ds_list_dict["no_tape_coll_did_list"]:
389
+ # update no_staging_datasets for all collections without constituent datasets on tape source
390
+ tmpLog.debug(f"collections without constituent datasets on tape source: {no_tape_coll_did_list}")
391
+ no_staging_datasets.update(set(no_tape_coll_did_list))
392
+ if to_skip_ds_list := ds_list_dict["to_skip_ds_list"]:
393
+ # update no_staging_datasets with secondary datasets
394
+ tmpLog.debug(f"datasets not required to check about data carousel (non-master input): {to_skip_ds_list}")
395
+ no_staging_datasets.update(set(to_skip_ds_list))
396
+ if datadisk_ds_list := ds_list_dict["datadisk_ds_list"]:
397
+ # update no_staging_datasets with datasets already on datadisks
398
+ tmpLog.debug(f"datasets already on datadisks: {datadisk_ds_list}")
399
+ no_staging_datasets.update(set(datadisk_ds_list))
400
+ disk_datasets.update(set(datadisk_ds_list))
401
+ if unfound_ds_list := ds_list_dict["unfound_ds_list"]:
402
+ # some datasets unfound
403
+ if taskParamMap.get("waitInput"):
404
+ # task has waitInput; to be checked again by TaskRefiner later
405
+ tmpLog.debug(f"task has waitInput, waiting for input datasets to be created: {unfound_ds_list}; skipped")
406
+ else:
407
+ # not to wait input; update no_staging_datasets with datasets unfound on tape or datadisk (regardless of local/scratch disks)
408
+ tmpLog.debug(f"some input datasets not found on tape or datadisk: {unfound_ds_list}")
409
+ no_staging_datasets.update(set(unfound_ds_list))
410
+ if not prestaging_list and (not unfound_coll_list or not taskParamMap.get("waitInput")):
411
+ # all input collections do not need staging (found, or unfound but waiting)
412
+ tmpLog.info("no need to prestage, try to resume task from staging")
413
+ # no dataset needs pre-staging; resume task from staging
414
+ self.taskBufferIF.sendCommandTaskPanda(jediTaskID, "TaskRefiner. No need to prestage. Resumed from staging", True, "resume")
415
+ if prestaging_list:
416
+ # something to prestage
417
+ if to_reuse_staging_ds_list := ds_list_dict["to_reuse_staging_ds_list"]:
418
+ # update to_staging_datasets with datasets to reuse existing staging DDM rules (de facto already staging, still need to submit DC requests)
419
+ tmpLog.debug(f"datasets to reuse existing staging DDM rules: {to_reuse_staging_ds_list}")
420
+ to_staging_datasets.update(set(to_reuse_staging_ds_list))
421
+ if to_reuse_staged_ds_list := ds_list_dict["to_reuse_staged_ds_list"]:
422
+ # update no_staging_datasets with datasets already staged (de facto already on disk)
423
+ tmpLog.debug(f"datasets already staged by existing DDM rules: {to_reuse_staged_ds_list}")
424
+ no_staging_datasets.update(set(to_reuse_staged_ds_list))
425
+ if tape_coll_did_list := ds_list_dict["tape_coll_did_list"]:
426
+ # update to_staging_datasets with collections with datasets only on tapes
427
+ to_staging_datasets.update(set(tape_coll_did_list))
428
+ if tape_ds_list := ds_list_dict["tape_ds_list"]:
429
+ # update to_staging_datasets with datasets only on tapes
430
+ to_staging_datasets.update(set(tape_ds_list))
431
+ if to_pin_ds_list := ds_list_dict["to_pin_ds_list"]:
432
+ # update no_staging_datasets with datasets to pin on datadisks (already on disk but without rule)
433
+ tmpLog.debug(f"datasets to pin to datadisks: {to_pin_ds_list}")
434
+ no_staging_datasets.update(set(to_pin_ds_list))
435
+ # submit options
436
+ dc_submit_options = {}
437
+ if taskParamMap.get("remove_rule_when_done"):
438
+ # remove rule when done
439
+ dc_submit_options["remove_when_done"] = True
440
+ if task_type := taskParamMap.get("taskType"):
441
+ dc_submit_options["task_type"] = task_type
442
+ # if task_user := taskParamMap.get("userName"):
443
+ # dc_submit_options["task_user"] = task_user
444
+ # if task_group := taskParamMap.get("workingGroup"):
445
+ # dc_submit_options["task_group"] = task_group
446
+ # submit data carousel requests for dataset to pre-stage
447
+ tmpLog.info("to prestage, submitting data carousel requests")
448
+ tmp_ret = self.data_carousel_interface.submit_data_carousel_requests(jediTaskID, prestaging_list, options=dc_submit_options)
449
+ if tmp_ret:
450
+ tmpLog.info("submitted data carousel requests")
451
+ if to_staging_datasets <= no_staging_datasets:
452
+ tmpLog.info("all datasets do not need staging (to pin or already staged); skip staging")
453
+ elif disk_datasets:
454
+ tmpLog.info("some datasets are on datadisks; skip staging")
455
+ else:
456
+ taskParamMap["toStaging"] = True
457
+ tmpLog.info("set toStaging")
458
+ else:
459
+ # failed to submit data carousel requests; skip and retry in next cycle
460
+ tmpLog.error("failed to submit data carousel requests; skip and retry next time")
461
+ continue
462
+ if related_dcreq_ids := ds_list_dict["related_dcreq_ids"]:
463
+ tmp_ret = self.data_carousel_interface.add_data_carousel_relations(jediTaskID, related_dcreq_ids)
464
+ if tmp_ret:
465
+ tmpLog.info(f"added relations to existing data carousel requests: {related_dcreq_ids}")
466
+ else:
467
+ tmpLog.error(f"failed to add relations to existing data carousel requests: {related_dcreq_ids}; skipped")
468
+ except Exception:
469
+ errtype, errvalue = sys.exc_info()[:2]
470
+ errStr = f"failed to check about data carousel with {errtype.__name__}:{errvalue}"
471
+ tmpLog.error(errStr)
472
+ tmpStat = Interaction.SC_FAILED
473
+ # staging
474
+ if tmpStat == Interaction.SC_SUCCEEDED:
475
+ if "toStaging" in taskParamMap and taskStatus not in ["staged", "rerefine"]:
476
+ errStr = "wait until staging is done"
477
+ impl.taskSpec.status = "staging"
478
+ impl.taskSpec.oldStatus = taskStatus
479
+ impl.taskSpec.setErrDiag(errStr)
480
+ # not to update some task attributes
481
+ impl.taskSpec.resetRefinedAttrs()
482
+ tmpLog.info(errStr)
483
+ self.taskBufferIF.updateTask_JEDI(
484
+ impl.taskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus], updateDEFT=False, setFrozenTime=False
485
+ )
486
+ tmpLog.info("update task status to staging")
487
+ continue
488
+ # adjust specs after refining
489
+ if tmpStat == Interaction.SC_SUCCEEDED:
490
+ try:
491
+ if impl.taskSpec.inputPreStaging():
492
+ # for now, no staging for all secondary datasets
493
+ tmp_ds_set = set()
494
+ for dataset_spec in impl.inSecDatasetSpecList:
495
+ dataset_spec.set_no_staging(True)
496
+ tmp_ds_set.add(dataset_spec.datasetName)
497
+ if tmp_ds_set:
498
+ tmpLog.debug(f"set no_staging for secondary datasets: {list(tmp_ds_set)}")
499
+ if no_staging_datasets:
500
+ # discard None if any
501
+ no_staging_datasets.discard(None)
502
+ # set no_staging attribute for datasets not requiring staging
503
+ tmp_ds_set = set()
504
+ for dataset_spec in impl.inMasterDatasetSpec:
505
+ dataset_name = dataset_spec.datasetName
506
+ dataset_did = None
507
+ try:
508
+ dataset_did = rucioAPI.get_did_str(dataset_name)
509
+ except Exception:
510
+ pass
511
+ if (
512
+ dataset_name in no_staging_datasets
513
+ or dataset_did in no_staging_datasets
514
+ or (dataset_name not in to_staging_datasets and dataset_did not in to_staging_datasets)
515
+ ):
516
+ dataset_spec.set_no_staging(True)
517
+ tmp_ds_set.add(dataset_name)
518
+ if tmp_ds_set:
519
+ tmpLog.debug(f"set no_staging for master datasets not to stage: {list(tmp_ds_set)}")
520
+ except Exception:
521
+ errtype, errvalue = sys.exc_info()[:2]
522
+ errStr = f"failed to adjust spec after refining {errtype.__name__}:{errvalue}"
523
+ tmpLog.error(errStr)
524
+ tmpStat = Interaction.SC_FAILED
525
+ # register
526
+ if tmpStat != Interaction.SC_SUCCEEDED:
527
+ tmpLog.error("failed to refine the task")
528
+ if impl is None or impl.taskSpec is None:
529
+ tmpTaskSpec = JediTaskSpec()
530
+ tmpTaskSpec.jediTaskID = jediTaskID
531
+ else:
532
+ tmpTaskSpec = impl.taskSpec
533
+ tmpTaskSpec.status = "tobroken"
534
+ if errStr != "":
535
+ tmpTaskSpec.setErrDiag(errStr, True)
536
+ self.taskBufferIF.updateTask_JEDI(tmpTaskSpec, {"jediTaskID": tmpTaskSpec.jediTaskID}, oldStatus=[taskStatus])
537
+ else:
538
+ tmpLog.info("registering")
539
+ # fill JEDI tables
540
+ try:
541
+ # enable protection against task duplication
542
+ if "uniqueTaskName" in taskParamMap and taskParamMap["uniqueTaskName"] and not impl.taskSpec.checkPreProcessed():
543
+ uniqueTaskName = True
544
+ else:
545
+ uniqueTaskName = False
546
+ strTaskParams = None
547
+ if impl.updatedTaskParams is not None:
548
+ strTaskParams = RefinerUtils.encodeJSON(impl.updatedTaskParams)
549
+ if taskStatus in ["registered", "staged"]:
550
+ # unset pre-process flag
551
+ if impl.taskSpec.checkPreProcessed():
552
+ impl.taskSpec.setPostPreProcess()
553
+ # full registration
554
+ tmpStat, newTaskStatus = self.taskBufferIF.registerTaskInOneShot_JEDI(
555
+ jediTaskID,
556
+ impl.taskSpec,
557
+ impl.inMasterDatasetSpec,
558
+ impl.inSecDatasetSpecList,
559
+ impl.outDatasetSpecList,
560
+ impl.outputTemplateMap,
561
+ impl.jobParamsTemplate,
562
+ strTaskParams,
563
+ impl.unmergeMasterDatasetSpec,
564
+ impl.unmergeDatasetSpecMap,
565
+ uniqueTaskName,
566
+ taskStatus,
567
+ )
568
+ if not tmpStat:
569
+ tmpErrStr = "failed to register the task to JEDI in a single shot"
570
+ tmpLog.error(tmpErrStr)
571
+ tmpTaskSpec = JediTaskSpec()
572
+ tmpTaskSpec.status = newTaskStatus
573
+ tmpTaskSpec.errorDialog = impl.taskSpec.errorDialog
574
+ tmpTaskSpec.setErrDiag(tmpErrStr, True)
575
+ self.taskBufferIF.updateTask_JEDI(tmpTaskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus])
576
+ tmp_msg = f"set task_status={newTaskStatus} sourceLabel={prodSourceLabel}"
577
+ tmpLog.info(tmp_msg)
578
+ tmpLog.sendMsg(tmp_msg, self.msgType)
579
+ # send message to contents feeder if the task is registered
580
+ if tmpStat and impl.taskSpec.is_msg_driven():
581
+ push_ret = self.taskBufferIF.push_task_trigger_message("jedi_contents_feeder", jediTaskID, task_spec=impl.taskSpec)
582
+ if push_ret:
583
+ tmpLog.debug("pushed trigger message to jedi_contents_feeder")
584
+ else:
585
+ tmpLog.warning("failed to push trigger message to jedi_contents_feeder")
586
+ else:
587
+ # disable scouts if previous attempt didn't use it
588
+ if not impl.taskSpec.useScout(splitRule):
589
+ impl.taskSpec.setUseScout(False)
590
+ # disallow to reset some attributes
591
+ impl.taskSpec.reserve_old_attributes()
592
+ # update task with new params
593
+ self.taskBufferIF.updateTask_JEDI(impl.taskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus])
594
+ # appending for incremental execution
595
+ tmpStat = self.taskBufferIF.appendDatasets_JEDI(jediTaskID, impl.inMasterDatasetSpec, impl.inSecDatasetSpecList)
596
+ if not tmpStat:
597
+ tmpLog.error("failed to append datasets for incexec")
598
+ except Exception:
599
+ errtype, errvalue = sys.exc_info()[:2]
600
+ tmpErrStr = f"failed to register the task to JEDI with {errtype.__name__}:{errvalue}"
601
+ tmpLog.error(tmpErrStr)
602
+ else:
603
+ tmpLog.info("done")
604
+ except Exception:
605
+ errtype, errvalue = sys.exc_info()[:2]
606
+ logger.error(f"{self.__class__.__name__} failed in runImpl() with {errtype.__name__}:{errvalue}")
607
+
608
+
609
+ def launcher(commuChannel, taskBufferIF, ddmIF, vos=None, prodSourceLabels=None):
610
+ p = TaskRefiner(commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels)
611
+ p.start()
@@ -0,0 +1,17 @@
1
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
2
+
3
+ from pandajedi.jediconfig import jedi_config
4
+ from pandajedi.jedicore.FactoryBase import FactoryBase
5
+
6
+ logger = PandaLogger().getLogger(__name__.split(".")[-1])
7
+
8
+
9
+ # factory class for task setup
10
+ class TaskSetupper(FactoryBase):
11
+ # constructor
12
+ def __init__(self, vo, sourceLabel):
13
+ FactoryBase.__init__(self, vo, sourceLabel, logger, jedi_config.tasksetup.modConfig)
14
+
15
+ # main
16
+ def doSetup(self, taskSpec, datasetToRegister, pandaJobs):
17
+ return self.getImpl(taskSpec.vo, taskSpec.prodSourceLabel).doSetup(taskSpec, datasetToRegister, pandaJobs)