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,268 @@
1
+ import datetime
2
+ import sys
3
+ import time
4
+
5
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
6
+ from pandacommon.pandautils.PandaUtils import naive_utcnow
7
+
8
+ from pandajedi.jediconfig import jedi_config
9
+ from pandajedi.jedicore import Interaction
10
+ from pandajedi.jedicore.FactoryBase import FactoryBase
11
+ from pandajedi.jedicore.MsgWrapper import MsgWrapper
12
+ from pandajedi.jedicore.ThreadUtils import ListWithLock, ThreadPool, WorkerThread
13
+
14
+ from .JediKnight import JediKnight
15
+
16
+ logger = PandaLogger().getLogger(__name__.split(".")[-1])
17
+
18
+
19
+ # worker class to refine TASK_PARAM to fill JEDI tables
20
+ class TaskBroker(JediKnight, FactoryBase):
21
+ # constructor
22
+ def __init__(self, commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels):
23
+ self.vos = self.parseInit(vos)
24
+ self.prodSourceLabels = self.parseInit(prodSourceLabels)
25
+ JediKnight.__init__(self, commuChannel, taskBufferIF, ddmIF, logger)
26
+ FactoryBase.__init__(self, self.vos, self.prodSourceLabels, logger, jedi_config.taskbroker.modConfig)
27
+
28
+ # main
29
+ def start(self):
30
+ # start base classes
31
+ JediKnight.start(self)
32
+ FactoryBase.initializeMods(self, self.taskBufferIF, self.ddmIF)
33
+ # go into main loop
34
+ while True:
35
+ startTime = naive_utcnow()
36
+ try:
37
+ # get logger
38
+ tmpLog = MsgWrapper(logger)
39
+ tmpLog.debug("start TaskBroker")
40
+ # get work queue mapper
41
+ workQueueMapper = self.taskBufferIF.getWorkQueueMap()
42
+ resource_types = self.taskBufferIF.load_resource_types()
43
+
44
+ # loop over all vos
45
+ for vo in self.vos:
46
+ # loop over all sourceLabels
47
+ for prodSourceLabel in self.prodSourceLabels:
48
+ # loop over all work queues
49
+ for workQueue in workQueueMapper.getAlignedQueueList(vo, prodSourceLabel):
50
+ for resource_type in resource_types:
51
+ wq_name = "_".join(workQueue.queue_name.split(" "))
52
+ msgLabel = f"vo={vo} label={prodSourceLabel} queue={wq_name} resource_type={resource_type.resource_name}: "
53
+ tmpLog.debug(msgLabel + "start")
54
+ # get the list of tasks to check
55
+ tmpList = self.taskBufferIF.getTasksToCheckAssignment_JEDI(vo, prodSourceLabel, workQueue, resource_type.resource_name)
56
+ if tmpList is None:
57
+ # failed
58
+ tmpLog.error(msgLabel + "failed to get the list of tasks to check")
59
+ else:
60
+ tmpLog.debug(msgLabel + f"got tasks_to_check={len(tmpList)}")
61
+ # put to a locked list
62
+ taskList = ListWithLock(tmpList)
63
+ # make thread pool
64
+ threadPool = ThreadPool()
65
+ # make workers
66
+ nWorker = jedi_config.taskbroker.nWorkers
67
+ for iWorker in range(nWorker):
68
+ thr = TaskCheckerThread(taskList, threadPool, self.taskBufferIF, self.ddmIF, self, vo, prodSourceLabel)
69
+ thr.start()
70
+ # join
71
+ threadPool.join()
72
+ # get the list of tasks to assign
73
+ tmpList = self.taskBufferIF.getTasksToAssign_JEDI(vo, prodSourceLabel, workQueue, resource_type.resource_name)
74
+ if tmpList is None:
75
+ # failed
76
+ tmpLog.error(msgLabel + "failed to get the list of tasks to assign")
77
+ else:
78
+ tmpLog.debug(msgLabel + f"got tasks_to_assign={len(tmpList)}")
79
+ # put to a locked list
80
+ taskList = ListWithLock(tmpList)
81
+ # make thread pool
82
+ threadPool = ThreadPool()
83
+ # make workers
84
+ nWorker = jedi_config.taskbroker.nWorkers
85
+ for iWorker in range(nWorker):
86
+ thr = TaskBrokerThread(
87
+ taskList,
88
+ threadPool,
89
+ self.taskBufferIF,
90
+ self.ddmIF,
91
+ self,
92
+ vo,
93
+ prodSourceLabel,
94
+ workQueue,
95
+ resource_type.resource_name,
96
+ )
97
+ thr.start()
98
+ # join
99
+ threadPool.join()
100
+ tmpLog.debug(msgLabel + "done")
101
+ except Exception:
102
+ errtype, errvalue = sys.exc_info()[:2]
103
+ tmpLog.error(f"failed in {self.__class__.__name__}.start() with {errtype.__name__} {errvalue}")
104
+ tmpLog.debug("done")
105
+ # sleep if needed
106
+ loopCycle = jedi_config.taskbroker.loopCycle
107
+ timeDelta = naive_utcnow() - startTime
108
+ sleepPeriod = loopCycle - timeDelta.seconds
109
+ if sleepPeriod > 0:
110
+ time.sleep(sleepPeriod)
111
+ # randomize cycle
112
+ self.randomSleep(max_val=loopCycle)
113
+
114
+
115
+ # thread for real worker
116
+ class TaskCheckerThread(WorkerThread):
117
+ # constructor
118
+ def __init__(self, taskList, threadPool, taskbufferIF, ddmIF, implFactory, vo, prodSourceLabel):
119
+ # initialize woker with no semaphore
120
+ WorkerThread.__init__(self, None, threadPool, logger)
121
+ # attributres
122
+ self.taskList = taskList
123
+ self.taskBufferIF = taskbufferIF
124
+ self.ddmIF = ddmIF.getInterface(vo)
125
+ self.implFactory = implFactory
126
+ self.vo = vo
127
+ self.prodSourceLabel = prodSourceLabel
128
+
129
+ # main
130
+ def runImpl(self):
131
+ while True:
132
+ try:
133
+ # get a part of list
134
+ nTasks = 100
135
+ taskList = self.taskList.get(nTasks)
136
+ totalTasks, idxTasks = self.taskList.stat()
137
+ # no more datasets
138
+ if len(taskList) == 0:
139
+ self.logger.debug(f"{self.__class__.__name__} terminating since no more items")
140
+ return
141
+ # make logger
142
+ tmpLog = MsgWrapper(self.logger)
143
+ tmpLog.info(f"start TaskCheckerThread {idxTasks}/{totalTasks} for jediTaskID={taskList}")
144
+ tmpStat = Interaction.SC_SUCCEEDED
145
+ # get TaskSpecs
146
+ taskSpecList = []
147
+ for jediTaskID in taskList:
148
+ tmpRet, taskSpec = self.taskBufferIF.getTaskWithID_JEDI(jediTaskID, False)
149
+ if tmpRet and taskSpec is not None:
150
+ taskSpecList.append(taskSpec)
151
+ else:
152
+ tmpLog.error(f"failed to get taskSpec for jediTaskID={jediTaskID}")
153
+ if taskSpecList != []:
154
+ # get impl
155
+ if tmpStat == Interaction.SC_SUCCEEDED:
156
+ tmpLog.info("getting Impl")
157
+ try:
158
+ impl = self.implFactory.getImpl(self.vo, self.prodSourceLabel)
159
+ if impl is None:
160
+ # task brokerage is undefined
161
+ tmpLog.error(f"task broker is undefined for vo={self.vo} sourceLabel={self.prodSourceLabel}")
162
+ tmpStat = Interaction.SC_FAILED
163
+ except Exception:
164
+ errtype, errvalue = sys.exc_info()[:2]
165
+ tmpLog.error(f"getImpl failed with {errtype.__name__}:{errvalue}")
166
+ tmpStat = Interaction.SC_FAILED
167
+ # check
168
+ if tmpStat == Interaction.SC_SUCCEEDED:
169
+ tmpLog.info(f"check with {impl.__class__.__name__}")
170
+ try:
171
+ tmpStat, taskCloudMap = impl.doCheck(taskSpecList)
172
+ except Exception:
173
+ errtype, errvalue = sys.exc_info()[:2]
174
+ tmpLog.error(f"doCheck failed with {errtype.__name__}:{errvalue}")
175
+ tmpStat = Interaction.SC_FAILED
176
+ # update
177
+ if tmpStat != Interaction.SC_SUCCEEDED:
178
+ tmpLog.error("failed to check assignment")
179
+ else:
180
+ tmpRet = self.taskBufferIF.setCloudToTasks_JEDI(taskCloudMap)
181
+ tmpLog.info(f"done with {tmpRet} for {str(taskCloudMap)}")
182
+ except Exception:
183
+ errtype, errvalue = sys.exc_info()[:2]
184
+ logger.error(f"{self.__class__.__name__} failed in runImpl() with {errtype.__name__}:{errvalue}")
185
+
186
+
187
+ # thread for real worker
188
+ class TaskBrokerThread(WorkerThread):
189
+ # constructor
190
+ def __init__(self, taskList, threadPool, taskbufferIF, ddmIF, implFactory, vo, prodSourceLabel, workQueue, resource_name):
191
+ # initialize woker with no semaphore
192
+ WorkerThread.__init__(self, None, threadPool, logger)
193
+ # attributres
194
+ self.taskList = taskList
195
+ self.taskBufferIF = taskbufferIF
196
+ self.ddmIF = ddmIF.getInterface(vo)
197
+ self.implFactory = implFactory
198
+ self.vo = vo
199
+ self.prodSourceLabel = prodSourceLabel
200
+ self.workQueue = workQueue
201
+ self.resource_name = resource_name
202
+
203
+ # main
204
+ def runImpl(self):
205
+ while True:
206
+ try:
207
+ # get a part of list
208
+ nTasks = 100
209
+ taskList = self.taskList.get(nTasks)
210
+ totalTasks, idxTasks = self.taskList.stat()
211
+ # no more datasets
212
+ if len(taskList) == 0:
213
+ self.logger.debug(f"{self.__class__.__name__} terminating since no more items")
214
+ return
215
+ # make logger
216
+ tmpLog = MsgWrapper(self.logger)
217
+ tmpLog.info(f"start TaskBrokerThread {idxTasks}/{totalTasks} for jediTaskID={taskList}")
218
+ tmpStat = Interaction.SC_SUCCEEDED
219
+ # get TaskSpecs
220
+ tmpListToAssign = []
221
+ for tmpTaskItem in taskList:
222
+ tmpListItem = self.taskBufferIF.getTasksToBeProcessed_JEDI(
223
+ None, None, None, None, None, simTasks=[tmpTaskItem], readMinFiles=True, fullSimulation=True
224
+ )
225
+ if tmpListItem is None:
226
+ # failed
227
+ tmpLog.error(f"failed to get the input chunks for jediTaskID={tmpTaskItem}")
228
+ tmpStat = Interaction.SC_FAILED
229
+ break
230
+ tmpListToAssign += tmpListItem
231
+ # get impl
232
+ if tmpStat == Interaction.SC_SUCCEEDED:
233
+ tmpLog.info("getting Impl")
234
+ try:
235
+ impl = self.implFactory.getImpl(self.vo, self.prodSourceLabel)
236
+ if impl is None:
237
+ # task refiner is undefined
238
+ tmpLog.error(f"task broker is undefined for vo={self.vo} sourceLabel={self.prodSourceLabel}")
239
+ tmpStat = Interaction.SC_FAILED
240
+ except Exception:
241
+ errtype, errvalue = sys.exc_info()[:2]
242
+ tmpLog.error(f"getImpl failed with {errtype.__name__}:{errvalue}")
243
+ tmpStat = Interaction.SC_FAILED
244
+ # brokerage
245
+ if tmpStat == Interaction.SC_SUCCEEDED:
246
+ tmpLog.info(f"brokerage with {impl.__class__.__name__} for {len(tmpListToAssign)} tasks ")
247
+ try:
248
+ tmpStat = impl.doBrokerage(tmpListToAssign, self.vo, self.prodSourceLabel, self.workQueue, self.resource_name)
249
+ except Exception:
250
+ errtype, errvalue = sys.exc_info()[:2]
251
+ tmpLog.error(f"doBrokerage failed with {errtype.__name__}:{errvalue}")
252
+ tmpStat = Interaction.SC_FAILED
253
+ # register
254
+ if tmpStat != Interaction.SC_SUCCEEDED:
255
+ tmpLog.error("failed")
256
+ else:
257
+ tmpLog.info("done")
258
+ except Exception:
259
+ errtype, errvalue = sys.exc_info()[:2]
260
+ logger.error(f"{self.__class__.__name__} failed in runImpl() with {errtype.__name__}:{errvalue}")
261
+
262
+
263
+ # launch
264
+
265
+
266
+ def launcher(commuChannel, taskBufferIF, ddmIF, vos=None, prodSourceLabels=None):
267
+ p = TaskBroker(commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels)
268
+ p.start()
@@ -0,0 +1,334 @@
1
+ import os
2
+ import re
3
+ import socket
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
12
+ from pandajedi.jedicore.MsgWrapper import MsgWrapper
13
+ from pandajedi.jedicore.ThreadUtils import ListWithLock, ThreadPool, WorkerThread
14
+ from pandajedi.jedirefine import RefinerUtils
15
+ from pandaserver.srvcore import CoreUtils
16
+ from pandaserver.taskbuffer.JediTaskSpec import JediTaskSpec
17
+
18
+ from .JediKnight import JediKnight
19
+
20
+ logger = PandaLogger().getLogger(__name__.split(".")[-1])
21
+
22
+
23
+ # worker class to kill/amend tasks
24
+ class TaskCommando(JediKnight):
25
+ # constructor
26
+ def __init__(self, commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels):
27
+ self.vos = self.parseInit(vos)
28
+ self.prodSourceLabels = self.parseInit(prodSourceLabels)
29
+ self.pid = f"{socket.getfqdn().split('.')[0]}-{os.getpid()}-dog"
30
+ JediKnight.__init__(self, commuChannel, taskBufferIF, ddmIF, logger)
31
+
32
+ # main
33
+ def start(self):
34
+ # start base classes
35
+ JediKnight.start(self)
36
+ # go into main loop
37
+ while True:
38
+ startTime = naive_utcnow()
39
+ try:
40
+ # get logger
41
+ tmpLog = MsgWrapper(logger)
42
+ tmpLog.debug("start")
43
+ # loop over all vos
44
+ for vo in self.vos:
45
+ # loop over all sourceLabels
46
+ for prodSourceLabel in self.prodSourceLabels:
47
+ # get the list of tasks to exec command
48
+ tmpList = self.taskBufferIF.getTasksToExecCommand_JEDI(vo, prodSourceLabel)
49
+ if tmpList is None:
50
+ # failed
51
+ tmpLog.error(f"failed to get the task list for vo={vo} label={prodSourceLabel}")
52
+ else:
53
+ tmpLog.debug(f"got {len(tmpList)} tasks")
54
+ # put to a locked list
55
+ taskList = ListWithLock(tmpList)
56
+ # make thread pool
57
+ threadPool = ThreadPool()
58
+ # make workers
59
+ nWorker = jedi_config.taskrefine.nWorkers
60
+ for iWorker in range(nWorker):
61
+ thr = TaskCommandoThread(taskList, threadPool, self.taskBufferIF, self.ddmIF, self.pid)
62
+ thr.start()
63
+ # join
64
+ threadPool.join()
65
+ tmpLog.debug("done")
66
+ except Exception as e:
67
+ tmpLog.error(f"failed in {self.__class__.__name__}.start() with {str(e)} {traceback.format_exc()}")
68
+ # sleep if needed
69
+ loopCycle = jedi_config.tcommando.loopCycle
70
+ timeDelta = naive_utcnow() - startTime
71
+ sleepPeriod = loopCycle - timeDelta.seconds
72
+ if sleepPeriod > 0:
73
+ time.sleep(sleepPeriod)
74
+ # randomize cycle
75
+ self.randomSleep(max_val=loopCycle)
76
+
77
+
78
+ # thread for real worker
79
+ class TaskCommandoThread(WorkerThread):
80
+ # constructor
81
+ def __init__(self, taskList, threadPool, taskbufferIF, ddmIF, pid):
82
+ # initialize woker with no semaphore
83
+ WorkerThread.__init__(self, None, threadPool, logger)
84
+ # attributres
85
+ self.taskList = taskList
86
+ self.taskBufferIF = taskbufferIF
87
+ self.ddmIF = ddmIF
88
+ self.msgType = "taskcommando"
89
+ self.pid = pid
90
+
91
+ # main
92
+ def runImpl(self):
93
+ while True:
94
+ try:
95
+ # get a part of list
96
+ nTasks = 10
97
+ taskList = self.taskList.get(nTasks)
98
+ # no more datasets
99
+ if len(taskList) == 0:
100
+ self.logger.debug(f"{self.__class__.__name__} terminating since no more items")
101
+ return
102
+ # loop over all tasks
103
+ for jediTaskID, commandMap in taskList:
104
+ # make logger
105
+ tmpLog = MsgWrapper(self.logger, f" < jediTaskID={jediTaskID} >")
106
+ commandStr = commandMap["command"]
107
+ commentStr = commandMap["comment"]
108
+ oldStatus = commandMap["oldStatus"]
109
+ tmpLog.info(f"start for {commandStr}")
110
+ tmpStat = Interaction.SC_SUCCEEDED
111
+ if commandStr in ["kill", "finish", "reassign"]:
112
+ tmpMsg = f"executing {commandStr}"
113
+ tmpLog.info(tmpMsg)
114
+ tmpLog.sendMsg(tmpMsg, self.msgType)
115
+ # loop twice to see immediate result
116
+ for iLoop in range(2):
117
+ # get active PandaIDs to be killed
118
+ if commandStr == "reassign" and commentStr is not None and "soft reassign" in commentStr:
119
+ pandaIDs = self.taskBufferIF.getQueuedPandaIDsWithTask_JEDI(jediTaskID)
120
+ elif commandStr == "reassign" and commentStr is not None and "nokill reassign" in commentStr:
121
+ pandaIDs = []
122
+ else:
123
+ pandaIDs = self.taskBufferIF.getPandaIDsWithTask_JEDI(jediTaskID, True)
124
+ if pandaIDs is None:
125
+ tmpLog.error(f"failed to get PandaIDs for jediTaskID={jediTaskID}")
126
+ tmpStat = Interaction.SC_FAILED
127
+ # kill jobs or update task
128
+ if tmpStat == Interaction.SC_SUCCEEDED:
129
+ if pandaIDs == []:
130
+ # done since no active jobs
131
+ tmpMsg = "completed cleaning jobs"
132
+ tmpLog.sendMsg(tmpMsg, self.msgType)
133
+ tmpLog.info(tmpMsg)
134
+ tmpTaskSpec = JediTaskSpec()
135
+ tmpTaskSpec.jediTaskID = jediTaskID
136
+ updateTaskStatus = True
137
+ if commandStr != "reassign":
138
+ # reset oldStatus
139
+ # keep oldStatus for task reassignment since it is reset when actually reassigned
140
+ tmpTaskSpec.forceUpdate("oldStatus")
141
+ else:
142
+ # extract cloud or site
143
+ if commentStr is not None:
144
+ tmp_instructions = CoreUtils.parse_reassign_comment(commentStr)
145
+ reassign_target = tmp_instructions.get("target")
146
+ reassign_value = tmp_instructions.get("value")
147
+ back_to_old_status = tmp_instructions.get("back_to_old_status")
148
+ tmpItems = commentStr.split(":")
149
+ if reassign_target == "cloud":
150
+ tmpTaskSpec.cloud = reassign_value
151
+ elif reassign_target == "nucleus":
152
+ tmpTaskSpec.nucleus = reassign_value
153
+ else:
154
+ tmpTaskSpec.site = reassign_value
155
+ tmpMsg = f"set {reassign_target}={reassign_value}"
156
+ if back_to_old_status:
157
+ tmpMsg += f", while keeping status={oldStatus}"
158
+ tmpLog.sendMsg(tmpMsg, self.msgType)
159
+ tmpLog.info(tmpMsg)
160
+ # back to oldStatus if necessary
161
+ if back_to_old_status:
162
+ tmpTaskSpec.status = oldStatus
163
+ tmpTaskSpec.forceUpdate("oldStatus")
164
+ updateTaskStatus = False
165
+ if commandStr == "reassign":
166
+ tmpTaskSpec.forceUpdate("errorDialog")
167
+ if commandStr == "finish":
168
+ # update datasets
169
+ tmpLog.info("updating datasets to finish")
170
+ tmpStat = self.taskBufferIF.updateDatasetsToFinishTask_JEDI(jediTaskID, self.pid)
171
+ if not tmpStat:
172
+ tmpLog.info("wait until datasets are updated to finish")
173
+ # ignore failGoalUnreached when manually finished
174
+ tmpStat, taskSpec = self.taskBufferIF.getTaskWithID_JEDI(jediTaskID)
175
+ tmpTaskSpec.splitRule = taskSpec.splitRule
176
+ tmpTaskSpec.unsetFailGoalUnreached()
177
+ if updateTaskStatus:
178
+ tmpTaskSpec.status = JediTaskSpec.commandStatusMap()[commandStr]["done"]
179
+ tmpMsg = f"set task_status={tmpTaskSpec.status}"
180
+ tmpLog.sendMsg(tmpMsg, self.msgType)
181
+ tmpLog.info(tmpMsg)
182
+ tmpRet = self.taskBufferIF.updateTask_JEDI(tmpTaskSpec, {"jediTaskID": jediTaskID}, setOldModTime=True)
183
+ tmpLog.info(f"done with {str(tmpRet)}")
184
+ break
185
+ else:
186
+ # kill only in the first loop
187
+ if iLoop > 0:
188
+ break
189
+ # wait or kill jobs
190
+ if commentStr and "soft finish" in commentStr:
191
+ queuedPandaIDs = self.taskBufferIF.getQueuedPandaIDsWithTask_JEDI(jediTaskID)
192
+ tmpMsg = f"trying to kill {len(queuedPandaIDs)} queued jobs for soft finish"
193
+ tmpLog.info(tmpMsg)
194
+ tmpRet = self.taskBufferIF.killJobs(queuedPandaIDs, commentStr, "52", True)
195
+ tmpMsg = f"wating {len(pandaIDs)} jobs for soft finish"
196
+ tmpLog.info(tmpMsg)
197
+ tmpRet = True
198
+ tmpLog.info(f"done with {str(tmpRet)}")
199
+ break
200
+ else:
201
+ tmpMsg = f"trying to kill {len(pandaIDs)} jobs"
202
+ tmpLog.info(tmpMsg)
203
+ tmpLog.sendMsg(tmpMsg, self.msgType)
204
+ if commandStr in ["finish"]:
205
+ # force kill
206
+ tmpRet = self.taskBufferIF.killJobs(pandaIDs, commentStr, "52", True)
207
+ elif commandStr in ["reassign"]:
208
+ # force kill
209
+ tmpRet = self.taskBufferIF.killJobs(pandaIDs, commentStr, "51", True)
210
+ else:
211
+ # normal kill
212
+ tmpRet = self.taskBufferIF.killJobs(pandaIDs, commentStr, "50", True)
213
+ tmpLog.info(f"done with {str(tmpRet)}")
214
+ elif commandStr in ["retry", "incexec"]:
215
+ tmpMsg = f"executing {commandStr}"
216
+ tmpLog.info(tmpMsg)
217
+ tmpLog.sendMsg(tmpMsg, self.msgType)
218
+ # change task params for incexec
219
+ if commandStr == "incexec":
220
+ try:
221
+ # read task params
222
+ taskParam = self.taskBufferIF.getTaskParamsWithID_JEDI(jediTaskID)
223
+ taskParamMap = RefinerUtils.decodeJSON(taskParam)
224
+ # remove old sandbox file specified in the previous reattempt
225
+ taskParamMap.pop("fixedSandbox", None)
226
+ # convert new params
227
+ decoded = RefinerUtils.decodeJSON(commentStr)
228
+ if isinstance(decoded, dict):
229
+ # old style
230
+ newParamMap = decoded
231
+ command_qualifiers = []
232
+ else:
233
+ # new style
234
+ newParamMap, command_qualifiers = decoded
235
+ # change params
236
+ for newKey, newVal in newParamMap.items():
237
+ if newVal is None:
238
+ # delete
239
+ if newKey in taskParamMap:
240
+ del taskParamMap[newKey]
241
+ else:
242
+ # change
243
+ taskParamMap[newKey] = newVal
244
+ # overwrite sandbox
245
+ if "fixedSandbox" in taskParamMap:
246
+ # noBuild
247
+ for tmpParam in taskParamMap["jobParameters"]:
248
+ if tmpParam["type"] == "constant" and re.search("^-a [^ ]+$", tmpParam["value"]) is not None:
249
+ tmpParam["value"] = f"-a {taskParamMap['fixedSandbox']}"
250
+ # build
251
+ if "buildSpec" in taskParamMap:
252
+ taskParamMap["buildSpec"]["archiveName"] = taskParamMap["fixedSandbox"]
253
+ # merge
254
+ if "mergeSpec" in taskParamMap:
255
+ taskParamMap["mergeSpec"]["jobParameters"] = re.sub(
256
+ "-a [^ ]+", f"-a {taskParamMap['fixedSandbox']}", taskParamMap["mergeSpec"]["jobParameters"]
257
+ )
258
+ # encode new param
259
+ strTaskParams = RefinerUtils.encodeJSON(taskParamMap)
260
+ tmpRet = self.taskBufferIF.updateTaskParams_JEDI(jediTaskID, strTaskParams)
261
+ if tmpRet is not True:
262
+ tmpLog.error("failed to update task params")
263
+ continue
264
+ except Exception as e:
265
+ tmpLog.error(f"failed to change task params with {str(e)} {traceback.format_exc()}")
266
+ continue
267
+ else:
268
+ # command qualifiers for retry
269
+ command_qualifiers = commentStr.split()
270
+ # retry child tasks
271
+ retryChildTasks = "sole" not in command_qualifiers
272
+ # discard events
273
+ discardEvents = "discard" in command_qualifiers
274
+ # release un-staged files
275
+ releaseUnstaged = "staged" in command_qualifiers
276
+ # keep gshare and priority
277
+ keep_share_priority = "keep" in command_qualifiers
278
+ # ignore limit for hard-exhausted
279
+ ignore_hard_exhausted = "transcend" in command_qualifiers
280
+ # retry the task
281
+ tmpRet, newTaskStatus, retried_tasks = self.taskBufferIF.retryTask_JEDI(
282
+ jediTaskID,
283
+ commandStr,
284
+ retryChildTasks=retryChildTasks,
285
+ discardEvents=discardEvents,
286
+ release_unstaged=releaseUnstaged,
287
+ keep_share_priority=keep_share_priority,
288
+ ignore_hard_exhausted=ignore_hard_exhausted,
289
+ )
290
+ if tmpRet is True:
291
+ tmpMsg = f"set task_status={newTaskStatus}"
292
+ tmpLog.sendMsg(tmpMsg, self.msgType)
293
+ tmpLog.info(tmpMsg)
294
+ if newTaskStatus in ["rerefine", "ready"]:
295
+ tmpStat, task_spec = self.taskBufferIF.getTaskWithID_JEDI(jediTaskID)
296
+ if tmpStat and task_spec.is_msg_driven():
297
+ # msg driven
298
+ if newTaskStatus == "rerefine":
299
+ push_ret = self.taskBufferIF.push_task_trigger_message("jedi_contents_feeder", jediTaskID)
300
+ if push_ret:
301
+ tmpLog.debug("pushed trigger message to jedi_contents_feeder")
302
+ else:
303
+ tmpLog.warning("failed to push trigger message to jedi_contents_feeder")
304
+ elif newTaskStatus == "ready":
305
+ push_ret = self.taskBufferIF.push_task_trigger_message("jedi_job_generator", jediTaskID)
306
+ if push_ret:
307
+ tmpLog.debug("pushed trigger message to jedi_job_generator")
308
+ else:
309
+ tmpLog.warning("failed to push trigger message to jedi_job_generator")
310
+ # reset global share and priority
311
+ if not keep_share_priority:
312
+ for task_id in retried_tasks:
313
+ try:
314
+ global_share = RefinerUtils.get_initial_global_share(self.taskBufferIF, task_id)
315
+ self.taskBufferIF.reassignShare([task_id], global_share, True)
316
+ tmp_msg = f"reset gshare={global_share} to jediTaskID={task_id}"
317
+ tmpLog.info(tmp_msg)
318
+ except Exception as e:
319
+ tmpLog.error(f"failed to reset gshare for {task_id} with {str(e)}")
320
+
321
+ tmpLog.info(f"done with {tmpRet}")
322
+ else:
323
+ tmpLog.error("unknown command")
324
+ except Exception as e:
325
+ errStr = f"{self.__class__.__name__} failed in runImpl() with {str(e)} {traceback.format_exc()} "
326
+ logger.error(errStr)
327
+
328
+
329
+ # launch
330
+
331
+
332
+ def launcher(commuChannel, taskBufferIF, ddmIF, vos=None, prodSourceLabels=None):
333
+ p = TaskCommando(commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels)
334
+ 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 generator
10
+ class TaskGenerator(FactoryBase):
11
+ # constructor
12
+ def __init__(self, vo, sourceLabel):
13
+ FactoryBase.__init__(self, vo, sourceLabel, logger, jedi_config.taskgen.modConfig)
14
+
15
+ # main
16
+ def doGenerate(self, taskSpec, taskParamMap, **varMap):
17
+ return self.getImpl(taskSpec.vo, taskSpec.prodSourceLabel).doGenerate(taskSpec, taskParamMap, **varMap)